/*
This file is part of GNUnet.
- (C) 2010, 2011, 2012 Christian Grothoff
+ Copyright (C) 2010, 2011, 2012 Christian Grothoff
GNUnet is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
You should have received a copy of the GNU General Public License
along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
*/
/**
- * @file exit/gnunet-helper-exit.c
+ * @file exit/gnunet-helper-exit.c
*
* @brief the helper for exit nodes. Opens a virtual
* network-interface, sends data received on the if to stdout, sends
/**
* Need 'struct GNUNET_MessageHeader'.
*/
+#include "gnunet_crypto_lib.h"
#include "gnunet_common.h"
/**
#endif
+/**
+ * Open '/dev/null' and make the result the given
+ * file descriptor.
+ *
+ * @param target_fd desired FD to point to /dev/null
+ * @param flags open flags (O_RDONLY, O_WRONLY)
+ */
+static void
+open_dev_null (int target_fd,
+ int flags)
+{
+ int fd;
+
+ fd = open ("/dev/null", flags);
+ if (-1 == fd)
+ abort ();
+ if (fd == target_fd)
+ return;
+ if (-1 == dup2 (fd, target_fd))
+ {
+ (void) close (fd);
+ abort ();
+ }
+ (void) close (fd);
+}
+
/**
* Run the given command and wait for it to complete.
- *
+ *
* @param file name of the binary to run
* @param cmd command line arguments (as given to 'execv')
* @return 0 on success, 1 on any error
*/
static int
-fork_and_exec (const char *file,
+fork_and_exec (const char *file,
char *const cmd[])
{
int status;
pid = fork ();
if (-1 == pid)
{
- fprintf (stderr,
- "fork failed: %s\n",
+ fprintf (stderr,
+ "fork failed: %s\n",
strerror (errno));
return 1;
}
/* we are the child process */
/* close stdin/stdout to not cause interference
with the helper's main protocol! */
- (void) close (0);
- (void) close (1);
+ (void) close (0);
+ open_dev_null (0, O_RDONLY);
+ (void) close (1);
+ open_dev_null (1, O_WRONLY);
(void) execv (file, cmd);
/* can only get here on error */
- fprintf (stderr,
- "exec `%s' failed: %s\n",
+ fprintf (stderr,
+ "exec `%s' failed: %s\n",
file,
strerror (errno));
_exit (1);
}
/* keep running waitpid as long as the only error we get is 'EINTR' */
while ( (-1 == (ret = waitpid (pid, &status, 0))) &&
- (errno == EINTR) );
+ (errno == EINTR) );
if (-1 == ret)
{
- fprintf (stderr,
- "waitpid failed: %s\n",
+ fprintf (stderr,
+ "waitpid failed: %s\n",
strerror (errno));
return 1;
}
if (-1 == ioctl (fd, TUNSETIFF, (void *) &ifr))
{
- fprintf (stderr,
+ fprintf (stderr,
"Error with ioctl on `%s': %s\n", "/dev/net/tun",
strerror (errno));
(void) close (fd);
if (-1 == (fd = socket (PF_INET6, SOCK_DGRAM, 0)))
{
- fprintf (stderr, "Error creating socket: %s\n", strerror (errno));
+ fprintf (stderr, "Error creating socket: %s\n", strerror (errno));
exit (1);
}
/* write refers to reading from stdin, writing to fd_tun */
int write_open = 1;
- while ((1 == read_open) || (1 == write_open))
+ while ((1 == read_open) && (1 == write_open))
{
FD_ZERO (&fds_w);
FD_ZERO (&fds_r);
MAX_SIZE - sizeof (struct GNUNET_MessageHeader));
if (-1 == buftun_size)
{
- fprintf (stderr, "read-error: %s\n", strerror (errno));
+ fprintf (stderr,
+ "read-error: %s\n",
+ strerror (errno));
shutdown (fd_tun, SHUT_RD);
shutdown (1, SHUT_WR);
read_open = 0;
#if !DEBUG
if (errno != EPIPE)
#endif
- fprintf (stderr, "write-error to stdout: %s\n", strerror (errno));
+ fprintf (stderr,
+ "write-error to stdout: %s\n",
+ strerror (errno));
shutdown (fd_tun, SHUT_RD);
shutdown (1, SHUT_WR);
read_open = 0;
* @param argc must be 6
* @param argv 0: binary name ("gnunet-helper-exit")
* 1: tunnel interface name ("gnunet-exit")
- * 2: IPv4 "physical" interface name ("eth0"), or "%" to not do IPv4 NAT
+ * 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
fprintf (stderr, "Fatal: disabling both IPv4 and IPv6 makes no sense.\n");
return 1;
}
- if (0 == access ("/sbin/iptables", X_OK))
- sbin_iptables = "/sbin/iptables";
- else if (0 == access ("/usr/sbin/iptables", X_OK))
- sbin_iptables = "/usr/sbin/iptables";
- else
+ if (0 != strcmp (argv[2], "-"))
{
- fprintf (stderr,
- "Fatal: executable iptables not found in approved directories: %s\n",
- strerror (errno));
- return 1;
- }
- if (0 == access ("/sbin/sysctl", X_OK))
- sbin_sysctl = "/sbin/sysctl";
- else if (0 == access ("/usr/sbin/sysctl", X_OK))
- sbin_sysctl = "/usr/sbin/sysctl";
- else
- {
- fprintf (stderr,
- "Fatal: executable sysctl not found in approved directories: %s\n",
- strerror (errno));
- return 1;
+ if (0 == access ("/sbin/iptables", X_OK))
+ sbin_iptables = "/sbin/iptables";
+ else if (0 == access ("/usr/sbin/iptables", X_OK))
+ sbin_iptables = "/usr/sbin/iptables";
+ else
+ {
+ fprintf (stderr,
+ "Fatal: executable iptables not found in approved directories: %s\n",
+ strerror (errno));
+ return 1;
+ }
+ if (0 == access ("/sbin/sysctl", X_OK))
+ sbin_sysctl = "/sbin/sysctl";
+ else if (0 == access ("/usr/sbin/sysctl", X_OK))
+ sbin_sysctl = "/usr/sbin/sysctl";
+ else
+ {
+ fprintf (stderr,
+ "Fatal: executable sysctl not found in approved directories: %s\n",
+ strerror (errno));
+ return 1;
+ }
}
strncpy (dev, argv[1], IFNAMSIZ);
if (-1 == (fd_tun = init_tun (dev)))
{
- fprintf (stderr,
+ fprintf (stderr,
"Fatal: could not initialize tun-interface `%s' with IPv6 %s/%s and IPv4 %s/%s\n",
dev,
argv[3],
{
const char *address = argv[3];
long prefix_len = atol (argv[4]);
-
+
if ((prefix_len < 1) || (prefix_len > 127))
{
fprintf (stderr, "Fatal: prefix_len out of range\n");
return 1;
- }
- set_address6 (dev, address, prefix_len);
+ }
+ set_address6 (dev, address, prefix_len);
}
+ if (0 != strcmp (argv[2], "-"))
{
char *const sysctl_args[] =
{
{
fprintf (stderr,
"Failed to enable IPv6 forwarding. Will continue anyway.\n");
- }
+ }
}
}
{
const char *address = argv[5];
const char *mask = argv[6];
-
+
set_address4 (dev, address, mask);
}
+ if (0 != strcmp (argv[2], "-"))
{
- char *const sysctl_args[] =
- {
- "sysctl", "-w", "net.ipv4.ip_forward=1", NULL
- };
- if (0 != fork_and_exec (sbin_sysctl,
- sysctl_args))
{
- fprintf (stderr,
- "Failed to enable IPv4 forwarding. Will continue anyway.\n");
- }
- }
- if (0 != strcmp (argv[2], "%"))
- {
- char *const iptables_args[] =
- {
- "iptables", "-t", "nat", "-A", "POSTROUTING", "-o", argv[2], "-j", "MASQUERADE", NULL
- };
- if (0 != fork_and_exec (sbin_iptables,
- iptables_args))
+ char *const sysctl_args[] =
+ {
+ "sysctl", "-w", "net.ipv4.ip_forward=1", NULL
+ };
+ if (0 != fork_and_exec (sbin_sysctl,
+ sysctl_args))
+ {
+ fprintf (stderr,
+ "Failed to enable IPv4 forwarding. Will continue anyway.\n");
+ }
+ }
{
- fprintf (stderr,
- "Failed to enable IPv4 masquerading (NAT). Will continue anyway.\n");
- }
+ char *const iptables_args[] =
+ {
+ "iptables", "-t", "nat", "-A", "POSTROUTING", "-o", argv[2], "-j", "MASQUERADE", NULL
+ };
+ if (0 != fork_and_exec (sbin_iptables,
+ iptables_args))
+ {
+ fprintf (stderr,
+ "Failed to enable IPv4 masquerading (NAT). Will continue anyway.\n");
+ }
+ }
}
}
-
+
uid_t uid = getuid ();
#ifdef HAVE_SETRESUID
if (0 != setresuid (uid, uid, uid))