GNUnet  0.11.x
Data Structures | Macros | Functions | Variables
gnunet-helper-exit.c File Reference

the helper for exit nodes. More...

#include "platform.h"
#include <linux/if_tun.h>
#include "gnunet_crypto_lib.h"
#include "gnunet_common.h"
#include "gnunet_protocols.h"
Include dependency graph for gnunet-helper-exit.c:

Go to the source code of this file.

Data Structures

struct  in6_ifreq
 This is in linux/include/net/ipv6.h, but not always exported... More...
 

Macros

#define DEBUG   GNUNET_NO
 Need 'struct GNUNET_MessageHeader'. More...
 
#define MAX_SIZE   65536
 Maximum size of a GNUnet message (GNUNET_MAX_MESSAGE_SIZE) More...
 

Functions

static void open_dev_null (int target_fd, int flags)
 Open '/dev/null' and make the result the given file descriptor. More...
 
static int fork_and_exec (const char *file, char *const cmd[])
 Run the given command and wait for it to complete. More...
 
static int init_tun (char *dev)
 Creates a tun-interface called dev;. More...
 
static void set_address6 (const char *dev, const char *address, unsigned long prefix_len)
 Sets the IPv6-Address given in address on the interface dev. More...
 
static void set_address4 (const char *dev, const char *address, const char *mask)
 Sets the IPv4-Address given in address on the interface dev. More...
 
static void run (int fd_tun)
 Start forwarding to and from the tunnel. More...
 
int main (int argc, char **argv)
 Open VPN tunnel interface. More...
 

Variables

static const char * sbin_sysctl
 Path to 'sysctl' binary. More...
 
static const char * sbin_iptables
 Path to 'iptables' binary. More...
 

Detailed Description

the helper for exit nodes.

Opens a virtual network-interface, sends data received on the if to stdout, sends data received on stdin to the interface. The code also enables IPv4/IPv6 forwarding and NAT on the current system (the latter on an interface specified on the command-line); these changes to the network configuration are NOT automatically undone when the program is stopped (this is because we cannot be sure that some other application didn't enable them before or after us; also, these changes should be mostly harmless as it simply turns the system into a router).

Author
Philipp Tölke
Christian Grothoff

The following list of people have reviewed this code and considered it safe since the last modification (if you reviewed it, please have your name added to the list):

Definition in file gnunet-helper-exit.c.

Macro Definition Documentation

◆ DEBUG

#define DEBUG   GNUNET_NO

Need 'struct GNUNET_MessageHeader'.

Need VPN message types. Should we print (interesting|debug) messages that can happen during normal operation?

Definition at line 62 of file gnunet-helper-exit.c.

◆ MAX_SIZE

#define MAX_SIZE   65536

Maximum size of a GNUnet message (GNUNET_MAX_MESSAGE_SIZE)

Definition at line 67 of file gnunet-helper-exit.c.

Referenced by run().

Function Documentation

◆ open_dev_null()

static void open_dev_null ( int  target_fd,
int  flags 
)
static

Open '/dev/null' and make the result the given file descriptor.

Parameters
target_fddesired FD to point to /dev/null
flagsopen flags (O_RDONLY, O_WRONLY)

Definition at line 101 of file gnunet-helper-exit.c.

Referenced by fork_and_exec().

103 {
104  int fd;
105 
106  fd = open ("/dev/null", flags);
107  if (-1 == fd)
108  abort ();
109  if (fd == target_fd)
110  return;
111  if (-1 == dup2 (fd, target_fd))
112  {
113  (void) close (fd);
114  abort ();
115  }
116  (void) close (fd);
117 }
Here is the caller graph for this function:

◆ fork_and_exec()

static int fork_and_exec ( const char *  file,
char *const  cmd[] 
)
static

Run the given command and wait for it to complete.

Parameters
filename of the binary to run
cmdcommand line arguments (as given to 'execv')
Returns
0 on success, 1 on any error

Definition at line 128 of file gnunet-helper-exit.c.

References open_dev_null(), pid, ret, and status.

Referenced by main().

130 {
131  int status;
132  pid_t pid;
133  pid_t ret;
134 
135  pid = fork ();
136  if (-1 == pid)
137  {
138  fprintf (stderr,
139  "fork failed: %s\n",
140  strerror (errno));
141  return 1;
142  }
143  if (0 == pid)
144  {
145  /* we are the child process */
146  /* close stdin/stdout to not cause interference
147  with the helper's main protocol! */
148  (void) close (0);
149  open_dev_null (0, O_RDONLY);
150  (void) close (1);
151  open_dev_null (1, O_WRONLY);
152  (void) execv (file, cmd);
153  /* can only get here on error */
154  fprintf (stderr,
155  "exec `%s' failed: %s\n",
156  file,
157  strerror (errno));
158  _exit (1);
159  }
160  /* keep running waitpid as long as the only error we get is 'EINTR' */
161  while ((-1 == (ret = waitpid (pid, &status, 0))) &&
162  (errno == EINTR))
163  ;
164  if (-1 == ret)
165  {
166  fprintf (stderr,
167  "waitpid failed: %s\n",
168  strerror (errno));
169  return 1;
170  }
171  if (! (WIFEXITED (status) && (0 == WEXITSTATUS (status))))
172  return 1;
173  /* child process completed and returned success, we're happy */
174  return 0;
175 }
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static void open_dev_null(int target_fd, int flags)
Open &#39;/dev/null&#39; and make the result the given file descriptor.
uint16_t status
See PRISM_STATUS_*-constants.
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ init_tun()

static int init_tun ( char *  dev)
static

Creates a tun-interface called dev;.

Parameters
devis asumed to point to a char[IFNAMSIZ] if *dev == '\0', uses the name supplied by the kernel;
Returns
the fd to the tun or -1 on error

Definition at line 186 of file gnunet-helper-exit.c.

Referenced by main().

187 {
188  struct ifreq ifr;
189  int fd;
190 
191  if (NULL == dev)
192  {
193  errno = EINVAL;
194  return -1;
195  }
196 
197  if (-1 == (fd = open ("/dev/net/tun", O_RDWR)))
198  {
199  fprintf (stderr, "Error opening `%s': %s\n", "/dev/net/tun",
200  strerror (errno));
201  return -1;
202  }
203 
204  if (fd >= FD_SETSIZE)
205  {
206  fprintf (stderr, "File descriptor to large: %d", fd);
207  (void) close (fd);
208  return -1;
209  }
210 
211  memset (&ifr, 0, sizeof(ifr));
212  ifr.ifr_flags = IFF_TUN;
213 
214  if ('\0' != *dev)
215  strncpy (ifr.ifr_name, dev, IFNAMSIZ);
216 
217  if (-1 == ioctl (fd, TUNSETIFF, (void *) &ifr))
218  {
219  fprintf (stderr,
220  "Error with ioctl on `%s': %s\n", "/dev/net/tun",
221  strerror (errno));
222  (void) close (fd);
223  return -1;
224  }
225  strcpy (dev, ifr.ifr_name);
226  return fd;
227 }
Here is the caller graph for this function:

◆ set_address6()

static void set_address6 ( const char *  dev,
const char *  address,
unsigned long  prefix_len 
)
static

Sets the IPv6-Address given in address on the interface dev.

Parameters
devthe interface to configure
addressthe IPv6-Address
prefix_lenthe length of the network-prefix

Definition at line 238 of file gnunet-helper-exit.c.

References in6_ifreq::ifr6_addr, in6_ifreq::ifr6_ifindex, and in6_ifreq::ifr6_prefixlen.

Referenced by main().

239 {
240  struct ifreq ifr;
241  struct sockaddr_in6 sa6;
242  int fd;
243  struct in6_ifreq ifr6;
244 
245  /*
246  * parse the new address
247  */
248  memset (&sa6, 0, sizeof(struct sockaddr_in6));
249  sa6.sin6_family = AF_INET6;
250  if (1 != inet_pton (AF_INET6, address, &sa6.sin6_addr))
251  {
252  fprintf (stderr, "Failed to parse address `%s': %s\n", address,
253  strerror (errno));
254  exit (1);
255  }
256 
257  if (-1 == (fd = socket (PF_INET6, SOCK_DGRAM, 0)))
258  {
259  fprintf (stderr, "Error creating socket: %s\n", strerror (errno));
260  exit (1);
261  }
262 
263  memset (&ifr, 0, sizeof(struct ifreq));
264  /*
265  * Get the index of the if
266  */
267  strncpy (ifr.ifr_name, dev, IFNAMSIZ);
268  if (-1 == ioctl (fd, SIOGIFINDEX, &ifr))
269  {
270  fprintf (stderr, "ioctl failed at %d: %s\n", __LINE__, strerror (errno));
271  (void) close (fd);
272  exit (1);
273  }
274 
275  memset (&ifr6, 0, sizeof(struct in6_ifreq));
276  ifr6.ifr6_addr = sa6.sin6_addr;
277  ifr6.ifr6_ifindex = ifr.ifr_ifindex;
278  ifr6.ifr6_prefixlen = prefix_len;
279 
280  /*
281  * Set the address
282  */
283  if (-1 == ioctl (fd, SIOCSIFADDR, &ifr6))
284  {
285  fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__,
286  strerror (errno));
287  (void) close (fd);
288  exit (1);
289  }
290 
291  /*
292  * Get the flags
293  */
294  if (-1 == ioctl (fd, SIOCGIFFLAGS, &ifr))
295  {
296  fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__,
297  strerror (errno));
298  (void) close (fd);
299  exit (1);
300  }
301 
302  /*
303  * Add the UP and RUNNING flags
304  */
305  ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
306  if (-1 == ioctl (fd, SIOCSIFFLAGS, &ifr))
307  {
308  fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__,
309  strerror (errno));
310  (void) close (fd);
311  exit (1);
312  }
313 
314  if (0 != close (fd))
315  {
316  fprintf (stderr, "close failed: %s\n", strerror (errno));
317  exit (1);
318  }
319 }
This is in linux/include/net/ipv6.h, but not always exported...
static char * address
GNS address for this phone.
Here is the caller graph for this function:

◆ set_address4()

static void set_address4 ( const char *  dev,
const char *  address,
const char *  mask 
)
static

Sets the IPv4-Address given in address on the interface dev.

Parameters
devthe interface to configure
addressthe IPv4-Address
maskthe netmask

Definition at line 330 of file gnunet-helper-exit.c.

Referenced by main().

331 {
332  int fd;
333  struct sockaddr_in *addr;
334  struct ifreq ifr;
335 
336  memset (&ifr, 0, sizeof(struct ifreq));
337  addr = (struct sockaddr_in *) &(ifr.ifr_addr);
338  addr->sin_family = AF_INET;
339 
340  /*
341  * Parse the address
342  */
343  if (1 != inet_pton (AF_INET, address, &addr->sin_addr.s_addr))
344  {
345  fprintf (stderr, "Failed to parse address `%s': %s\n", address,
346  strerror (errno));
347  exit (1);
348  }
349 
350  if (-1 == (fd = socket (PF_INET, SOCK_DGRAM, 0)))
351  {
352  fprintf (stderr, "Error creating socket: %s\n", strerror (errno));
353  exit (1);
354  }
355 
356  strncpy (ifr.ifr_name, dev, IFNAMSIZ);
357 
358  /*
359  * Set the address
360  */
361  if (-1 == ioctl (fd, SIOCSIFADDR, &ifr))
362  {
363  fprintf (stderr, "ioctl failed at %d: %s\n", __LINE__, strerror (errno));
364  (void) close (fd);
365  exit (1);
366  }
367 
368  /*
369  * Parse the netmask
370  */
371  addr = (struct sockaddr_in *) &(ifr.ifr_netmask);
372  if (1 != inet_pton (AF_INET, mask, &addr->sin_addr.s_addr))
373  {
374  fprintf (stderr, "Failed to parse address `%s': %s\n", mask,
375  strerror (errno));
376  (void) close (fd);
377  exit (1);
378  }
379 
380  /*
381  * Set the netmask
382  */
383  if (-1 == ioctl (fd, SIOCSIFNETMASK, &ifr))
384  {
385  fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__,
386  strerror (errno));
387  (void) close (fd);
388  exit (1);
389  }
390 
391  /*
392  * Get the flags
393  */
394  if (-1 == ioctl (fd, SIOCGIFFLAGS, &ifr))
395  {
396  fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__,
397  strerror (errno));
398  (void) close (fd);
399  exit (1);
400  }
401 
402  /*
403  * Add the UP and RUNNING flags
404  */
405  ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
406  if (-1 == ioctl (fd, SIOCSIFFLAGS, &ifr))
407  {
408  fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__,
409  strerror (errno));
410  (void) close (fd);
411  exit (1);
412  }
413 
414  if (0 != close (fd))
415  {
416  fprintf (stderr, "close failed: %s\n", strerror (errno));
417  (void) close (fd);
418  exit (1);
419  }
420 }
static char * address
GNS address for this phone.
Here is the caller graph for this function:

◆ run()

static void run ( int  fd_tun)
static

Start forwarding to and from the tunnel.

Parameters
fd_tuntunnel FD

Definition at line 429 of file gnunet-helper-exit.c.

References GNUNET_MESSAGE_TYPE_VPN_HELPER, MAX_SIZE, GNUNET_MessageHeader::size, and GNUNET_MessageHeader::type.

Referenced by main().

430 {
431  /*
432  * The buffer filled by reading from fd_tun
433  */
434  unsigned char buftun[MAX_SIZE];
435  ssize_t buftun_size = 0;
436  unsigned char *buftun_read = NULL;
437 
438  /*
439  * The buffer filled by reading from stdin
440  */
441  unsigned char bufin[MAX_SIZE];
442  ssize_t bufin_size = 0;
443  size_t bufin_rpos = 0;
444  unsigned char *bufin_read = NULL;
445 
446  fd_set fds_w;
447  fd_set fds_r;
448 
449  /* read refers to reading from fd_tun, writing to stdout */
450  int read_open = 1;
451 
452  /* write refers to reading from stdin, writing to fd_tun */
453  int write_open = 1;
454 
455  while ((1 == read_open) && (1 == write_open))
456  {
457  FD_ZERO (&fds_w);
458  FD_ZERO (&fds_r);
459 
460  /*
461  * We are supposed to read and the buffer is empty
462  * -> select on read from tun
463  */
464  if (read_open && (0 == buftun_size))
465  FD_SET (fd_tun, &fds_r);
466 
467  /*
468  * We are supposed to read and the buffer is not empty
469  * -> select on write to stdout
470  */
471  if (read_open && (0 != buftun_size))
472  FD_SET (1, &fds_w);
473 
474  /*
475  * We are supposed to write and the buffer is empty
476  * -> select on read from stdin
477  */
478  if (write_open && (NULL == bufin_read))
479  FD_SET (0, &fds_r);
480 
481  /*
482  * We are supposed to write and the buffer is not empty
483  * -> select on write to tun
484  */
485  if (write_open && (NULL != bufin_read))
486  FD_SET (fd_tun, &fds_w);
487 
488  int r = select (fd_tun + 1, &fds_r, &fds_w, NULL, NULL);
489 
490  if (-1 == r)
491  {
492  if (EINTR == errno)
493  continue;
494  fprintf (stderr, "select failed: %s\n", strerror (errno));
495  exit (1);
496  }
497 
498  if (r > 0)
499  {
500  if (FD_ISSET (fd_tun, &fds_r))
501  {
502  buftun_size =
503  read (fd_tun, buftun + sizeof(struct GNUNET_MessageHeader),
504  MAX_SIZE - sizeof(struct GNUNET_MessageHeader));
505  if (-1 == buftun_size)
506  {
507  fprintf (stderr,
508  "read-error: %s\n",
509  strerror (errno));
510  shutdown (fd_tun, SHUT_RD);
511  shutdown (1, SHUT_WR);
512  read_open = 0;
513  buftun_size = 0;
514  }
515  else if (0 == buftun_size)
516  {
517 #if DEBUG
518  fprintf (stderr, "EOF on tun\n");
519 #endif
520  shutdown (fd_tun, SHUT_RD);
521  shutdown (1, SHUT_WR);
522  read_open = 0;
523  buftun_size = 0;
524  }
525  else
526  {
527  buftun_read = buftun;
528  struct GNUNET_MessageHeader *hdr =
529  (struct GNUNET_MessageHeader *) buftun;
530  buftun_size += sizeof(struct GNUNET_MessageHeader);
531  hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
532  hdr->size = htons (buftun_size);
533  }
534  }
535  else if (FD_ISSET (1, &fds_w))
536  {
537  ssize_t written = write (1, buftun_read, buftun_size);
538 
539  if (-1 == written)
540  {
541 #if ! DEBUG
542  if (errno != EPIPE)
543 #endif
544  fprintf (stderr,
545  "write-error to stdout: %s\n",
546  strerror (errno));
547  shutdown (fd_tun, SHUT_RD);
548  shutdown (1, SHUT_WR);
549  read_open = 0;
550  buftun_size = 0;
551  }
552  else if (0 == written)
553  {
554  fprintf (stderr, "write returned 0!?\n");
555  exit (1);
556  }
557  else
558  {
559  buftun_size -= written;
560  buftun_read += written;
561  }
562  }
563 
564  if (FD_ISSET (0, &fds_r))
565  {
566  bufin_size = read (0, bufin + bufin_rpos, MAX_SIZE - bufin_rpos);
567  if (-1 == bufin_size)
568  {
569  fprintf (stderr, "read-error: %s\n", strerror (errno));
570  shutdown (0, SHUT_RD);
571  shutdown (fd_tun, SHUT_WR);
572  write_open = 0;
573  bufin_size = 0;
574  }
575  else if (0 == bufin_size)
576  {
577 #if DEBUG
578  fprintf (stderr, "EOF on stdin\n");
579 #endif
580  shutdown (0, SHUT_RD);
581  shutdown (fd_tun, SHUT_WR);
582  write_open = 0;
583  bufin_size = 0;
584  }
585  else
586  {
587  struct GNUNET_MessageHeader *hdr;
588 
589 PROCESS_BUFFER:
590  bufin_rpos += bufin_size;
591  if (bufin_rpos < sizeof(struct GNUNET_MessageHeader))
592  continue;
593  hdr = (struct GNUNET_MessageHeader *) bufin;
594  if (ntohs (hdr->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER)
595  {
596  fprintf (stderr, "protocol violation!\n");
597  exit (1);
598  }
599  if (ntohs (hdr->size) > bufin_rpos)
600  continue;
601  bufin_read = bufin + sizeof(struct GNUNET_MessageHeader);
602  bufin_size = ntohs (hdr->size) - sizeof(struct GNUNET_MessageHeader);
603  bufin_rpos -= bufin_size + sizeof(struct GNUNET_MessageHeader);
604  }
605  }
606  else if (FD_ISSET (fd_tun, &fds_w))
607  {
608  ssize_t written = write (fd_tun, bufin_read, bufin_size);
609 
610  if (-1 == written)
611  {
612  fprintf (stderr, "write-error to tun: %s\n", strerror (errno));
613  shutdown (0, SHUT_RD);
614  shutdown (fd_tun, SHUT_WR);
615  write_open = 0;
616  bufin_size = 0;
617  }
618  else if (0 == written)
619  {
620  fprintf (stderr, "write returned 0!?\n");
621  exit (1);
622  }
623  else
624  {
625  bufin_size -= written;
626  bufin_read += written;
627  if (0 == bufin_size)
628  {
629  memmove (bufin, bufin_read, bufin_rpos);
630  bufin_read = NULL; /* start reading again */
631  bufin_size = 0;
632  goto PROCESS_BUFFER;
633  }
634  }
635  }
636  }
637  }
638 }
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
#define MAX_SIZE
Maximum size of a GNUnet message (GNUNET_MAX_MESSAGE_SIZE)
Header for all communications.
#define GNUNET_MESSAGE_TYPE_VPN_HELPER
Type of messages between the gnunet-vpn-helper and the daemon.
Here is the caller graph for this function:

◆ main()

int main ( int  argc,
char **  argv 
)

Open VPN tunnel interface.

Parameters
argcmust be 6
argv0: binary name ("gnunet-helper-exit") 1: tunnel interface name ("gnunet-exit") 2: "physical" interface name ("eth0"), or "-" to not setup NAT and routing 3: IPv6 address ("::1"), or "-" to skip IPv6 4: IPv6 netmask length in bits ("64") [ignored if #4 is "-"] 5: IPv4 address ("1.2.3.4"), or "-" to skip IPv4 6: IPv4 netmask ("255.255.0.0") [ignored if #4 is "-"]

Definition at line 655 of file gnunet-helper-exit.c.

References address, cleanup(), fork_and_exec(), global_ret, init_tun(), run(), sbin_iptables, sbin_sysctl, set_address4(), and set_address6().

656 {
657  char dev[IFNAMSIZ];
658  int fd_tun;
659  int global_ret;
660 
661  if (7 != argc)
662  {
663  fprintf (stderr, "Fatal: must supply 6 arguments!\n");
664  return 1;
665  }
666  if ((0 == strcmp (argv[3], "-")) &&
667  (0 == strcmp (argv[5], "-")))
668  {
669  fprintf (stderr, "Fatal: disabling both IPv4 and IPv6 makes no sense.\n");
670  return 1;
671  }
672  if (0 != strcmp (argv[2], "-"))
673  {
674 #ifdef IPTABLES
675  if (0 == access (IPTABLES, X_OK))
676  sbin_iptables = IPTABLES;
677  else
678 #endif
679  if (0 == access ("/sbin/iptables", X_OK))
680  sbin_iptables = "/sbin/iptables";
681  else if (0 == access ("/usr/sbin/iptables", X_OK))
682  sbin_iptables = "/usr/sbin/iptables";
683  else
684  {
685  fprintf (stderr,
686  "Fatal: executable iptables not found in approved directories: %s\n",
687  strerror (errno));
688  return 1;
689  }
690 #ifdef SYSCTL
691  if (0 == access (SYSCTL, X_OK))
692  sbin_sysctl = SYSCTL;
693  else
694 #endif
695  if (0 == access ("/sbin/sysctl", X_OK))
696  sbin_sysctl = "/sbin/sysctl";
697  else if (0 == access ("/usr/sbin/sysctl", X_OK))
698  sbin_sysctl = "/usr/sbin/sysctl";
699  else
700  {
701  fprintf (stderr,
702  "Fatal: executable sysctl not found in approved directories: %s\n",
703  strerror (errno));
704  return 1;
705  }
706  }
707 
708  strncpy (dev, argv[1], IFNAMSIZ);
709  dev[IFNAMSIZ - 1] = '\0';
710 
711  if (-1 == (fd_tun = init_tun (dev)))
712  {
713  fprintf (stderr,
714  "Fatal: could not initialize tun-interface `%s' with IPv6 %s/%s and IPv4 %s/%s\n",
715  dev,
716  argv[3],
717  argv[4],
718  argv[5],
719  argv[6]);
720  return 1;
721  }
722 
723  if (0 != strcmp (argv[3], "-"))
724  {
725  {
726  const char *address = argv[3];
727  long prefix_len = atol (argv[4]);
728 
729  if ((prefix_len < 1) || (prefix_len > 127))
730  {
731  fprintf (stderr, "Fatal: prefix_len out of range\n");
732  return 1;
733  }
734  set_address6 (dev, address, prefix_len);
735  }
736  if (0 != strcmp (argv[2], "-"))
737  {
738  char *const sysctl_args[] = {
739  "sysctl", "-w", "net.ipv6.conf.all.forwarding=1", NULL
740  };
741  if (0 != fork_and_exec (sbin_sysctl,
742  sysctl_args))
743  {
744  fprintf (stderr,
745  "Failed to enable IPv6 forwarding. Will continue anyway.\n");
746  }
747  }
748  }
749 
750  if (0 != strcmp (argv[5], "-"))
751  {
752  {
753  const char *address = argv[5];
754  const char *mask = argv[6];
755 
756  set_address4 (dev, address, mask);
757  }
758  if (0 != strcmp (argv[2], "-"))
759  {
760  {
761  char *const sysctl_args[] = {
762  "sysctl", "-w", "net.ipv4.ip_forward=1", NULL
763  };
764  if (0 != fork_and_exec (sbin_sysctl,
765  sysctl_args))
766  {
767  fprintf (stderr,
768  "Failed to enable IPv4 forwarding. Will continue anyway.\n");
769  }
770  }
771  {
772  char *const iptables_args[] = {
773  "iptables", "-t", "nat", "-A", "POSTROUTING", "-o", argv[2], "-j",
774  "MASQUERADE", NULL
775  };
776  if (0 != fork_and_exec (sbin_iptables,
777  iptables_args))
778  {
779  fprintf (stderr,
780  "Failed to enable IPv4 masquerading (NAT). Will continue anyway.\n");
781  }
782  }
783  }
784  }
785 
786  uid_t uid = getuid ();
787 #ifdef HAVE_SETRESUID
788  if (0 != setresuid (uid, uid, uid))
789  {
790  fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno));
791  global_ret = 2;
792  goto cleanup;
793  }
794 #else
795  if (0 != (setuid (uid) | seteuid (uid)))
796  {
797  fprintf (stderr, "Failed to setuid: %s\n", strerror (errno));
798  global_ret = 2;
799  goto cleanup;
800  }
801 #endif
802 
803  if (SIG_ERR == signal (SIGPIPE, SIG_IGN))
804  {
805  fprintf (stderr, "Failed to protect against SIGPIPE: %s\n",
806  strerror (errno));
807  /* no exit, we might as well die with SIGPIPE should it ever happen */
808  }
809  run (fd_tun);
810  global_ret = 0;
811 cleanup:
812  (void) close (fd_tun);
813  return global_ret;
814 }
static int init_tun(char *dev)
Creates a tun-interface called dev;.
static const char * sbin_iptables
Path to &#39;iptables&#39; binary.
static void run(int fd_tun)
Start forwarding to and from the tunnel.
static void cleanup(void *cls)
Function scheduled as very last function, cleans up after us.
static void set_address6(const char *dev, const char *address, unsigned long prefix_len)
Sets the IPv6-Address given in address on the interface dev.
static void set_address4(const char *dev, const char *address, const char *mask)
Sets the IPv4-Address given in address on the interface dev.
static const char * sbin_sysctl
Path to &#39;sysctl&#39; binary.
static int fork_and_exec(const char *file, char *const cmd[])
Run the given command and wait for it to complete.
static char * address
GNS address for this phone.
static int global_ret
Return value from main.
Here is the call graph for this function:

Variable Documentation

◆ sbin_sysctl

const char* sbin_sysctl
static

Path to 'sysctl' binary.

Definition at line 72 of file gnunet-helper-exit.c.

Referenced by main().

◆ sbin_iptables

const char* sbin_iptables
static

Path to 'iptables' binary.

Definition at line 77 of file gnunet-helper-exit.c.

Referenced by main().