GNUnet  0.10.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 100 of file gnunet-helper-exit.c.

Referenced by fork_and_exec().

102 {
103  int fd;
104 
105  fd = open("/dev/null", flags);
106  if (-1 == fd)
107  abort();
108  if (fd == target_fd)
109  return;
110  if (-1 == dup2(fd, target_fd))
111  {
112  (void)close(fd);
113  abort();
114  }
115  (void)close(fd);
116 }
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 127 of file gnunet-helper-exit.c.

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

Referenced by main().

129 {
130  int status;
131  pid_t pid;
132  pid_t ret;
133 
134  pid = fork();
135  if (-1 == pid)
136  {
137  fprintf(stderr,
138  "fork failed: %s\n",
139  strerror(errno));
140  return 1;
141  }
142  if (0 == pid)
143  {
144  /* we are the child process */
145  /* close stdin/stdout to not cause interference
146  with the helper's main protocol! */
147  (void)close(0);
148  open_dev_null(0, O_RDONLY);
149  (void)close(1);
150  open_dev_null(1, O_WRONLY);
151  (void)execv(file, cmd);
152  /* can only get here on error */
153  fprintf(stderr,
154  "exec `%s' failed: %s\n",
155  file,
156  strerror(errno));
157  _exit(1);
158  }
159  /* keep running waitpid as long as the only error we get is 'EINTR' */
160  while ((-1 == (ret = waitpid(pid, &status, 0))) &&
161  (errno == EINTR))
162  ;
163  if (-1 == ret)
164  {
165  fprintf(stderr,
166  "waitpid failed: %s\n",
167  strerror(errno));
168  return 1;
169  }
170  if (!(WIFEXITED(status) && (0 == WEXITSTATUS(status))))
171  return 1;
172  /* child process completed and returned success, we're happy */
173  return 0;
174 }
static int ret
Final status code.
Definition: gnunet-arm.c:89
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 185 of file gnunet-helper-exit.c.

Referenced by main().

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

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

Referenced by main().

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

Referenced by main().

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

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

Referenced by main().

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

655 {
656  char dev[IFNAMSIZ];
657  int fd_tun;
658  int global_ret;
659 
660  if (7 != argc)
661  {
662  fprintf(stderr, "Fatal: must supply 6 arguments!\n");
663  return 1;
664  }
665  if ((0 == strcmp(argv[3], "-")) &&
666  (0 == strcmp(argv[5], "-")))
667  {
668  fprintf(stderr, "Fatal: disabling both IPv4 and IPv6 makes no sense.\n");
669  return 1;
670  }
671  if (0 != strcmp(argv[2], "-"))
672  {
673 #ifdef IPTABLES
674  if (0 == access(IPTABLES, X_OK))
675  sbin_iptables = IPTABLES;
676  else
677 #endif
678  if (0 == access("/sbin/iptables", X_OK))
679  sbin_iptables = "/sbin/iptables";
680  else if (0 == access("/usr/sbin/iptables", X_OK))
681  sbin_iptables = "/usr/sbin/iptables";
682  else
683  {
684  fprintf(stderr,
685  "Fatal: executable iptables not found in approved directories: %s\n",
686  strerror(errno));
687  return 1;
688  }
689 #ifdef SYSCTL
690  if (0 == access(SYSCTL, X_OK))
691  sbin_sysctl = SYSCTL;
692  else
693 #endif
694  if (0 == access("/sbin/sysctl", X_OK))
695  sbin_sysctl = "/sbin/sysctl";
696  else if (0 == access("/usr/sbin/sysctl", X_OK))
697  sbin_sysctl = "/usr/sbin/sysctl";
698  else
699  {
700  fprintf(stderr,
701  "Fatal: executable sysctl not found in approved directories: %s\n",
702  strerror(errno));
703  return 1;
704  }
705  }
706 
707  strncpy(dev, argv[1], IFNAMSIZ);
708  dev[IFNAMSIZ - 1] = '\0';
709 
710  if (-1 == (fd_tun = init_tun(dev)))
711  {
712  fprintf(stderr,
713  "Fatal: could not initialize tun-interface `%s' with IPv6 %s/%s and IPv4 %s/%s\n",
714  dev,
715  argv[3],
716  argv[4],
717  argv[5],
718  argv[6]);
719  return 1;
720  }
721 
722  if (0 != strcmp(argv[3], "-"))
723  {
724  {
725  const char *address = argv[3];
726  long prefix_len = atol(argv[4]);
727 
728  if ((prefix_len < 1) || (prefix_len > 127))
729  {
730  fprintf(stderr, "Fatal: prefix_len out of range\n");
731  return 1;
732  }
733  set_address6(dev, address, prefix_len);
734  }
735  if (0 != strcmp(argv[2], "-"))
736  {
737  char *const sysctl_args[] =
738  {
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  {
763  "sysctl", "-w", "net.ipv4.ip_forward=1", NULL
764  };
765  if (0 != fork_and_exec(sbin_sysctl,
766  sysctl_args))
767  {
768  fprintf(stderr,
769  "Failed to enable IPv4 forwarding. Will continue anyway.\n");
770  }
771  }
772  {
773  char *const iptables_args[] =
774  {
775  "iptables", "-t", "nat", "-A", "POSTROUTING", "-o", argv[2], "-j", "MASQUERADE", NULL
776  };
777  if (0 != fork_and_exec(sbin_iptables,
778  iptables_args))
779  {
780  fprintf(stderr,
781  "Failed to enable IPv4 masquerading (NAT). Will continue anyway.\n");
782  }
783  }
784  }
785  }
786 
787  uid_t uid = getuid();
788 #ifdef HAVE_SETRESUID
789  if (0 != setresuid(uid, uid, uid))
790  {
791  fprintf(stderr, "Failed to setresuid: %s\n", strerror(errno));
792  global_ret = 2;
793  goto cleanup;
794  }
795 #else
796  if (0 != (setuid(uid) | seteuid(uid)))
797  {
798  fprintf(stderr, "Failed to setuid: %s\n", strerror(errno));
799  global_ret = 2;
800  goto cleanup;
801  }
802 #endif
803 
804  if (SIG_ERR == signal(SIGPIPE, SIG_IGN))
805  {
806  fprintf(stderr, "Failed to protect against SIGPIPE: %s\n",
807  strerror(errno));
808  /* no exit, we might as well die with SIGPIPE should it ever happen */
809  }
810  run(fd_tun);
811  global_ret = 0;
812 cleanup:
813  (void)close(fd_tun);
814  return global_ret;
815 }
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().