tighten formatting rules
[oweals/gnunet.git] / src / exit / gnunet-helper-exit.c
index 5a9be473c7d8a0a6b53dd6bc8356589e76e64384..cf322725d0b22fc4e0fc17ff8f579a27f9cef4e6 100644 (file)
@@ -1,25 +1,25 @@
 /*
      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
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     or (at your option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
      WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
+     Affero General Public License for more details.
 
-     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.
-*/
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
 
 /**
- * @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
@@ -47,6 +47,7 @@
 /**
  * Need 'struct GNUNET_MessageHeader'.
  */
+#include "gnunet_crypto_lib.h"
 #include "gnunet_common.h"
 
 /**
 #include "gnunet_protocols.h"
 
 /**
- * Maximum size of a GNUnet message (GNUNET_SERVER_MAX_MESSAGE_SIZE)
+ * Should we print (interesting|debug) messages that can happen during
+ * normal operation?
+ */
+#define DEBUG GNUNET_NO
+
+/**
+ * Maximum size of a GNUnet message (GNUNET_MAX_MESSAGE_SIZE)
  */
 #define MAX_SIZE 65536
 
@@ -77,23 +84,49 @@ static const char *sbin_iptables;
 struct in6_ifreq
 {
   struct in6_addr ifr6_addr;
-  uint32_t ifr6_prefixlen;
-  unsigned int ifr6_ifindex;
+  uint32_t ifr6_prefixlen; /* __u32 in the original */
+  int ifr6_ifindex;
 };
 #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, 
-              char *const cmd[])
+fork_and_exec (const char *file,
+               char *const cmd[])
 {
   int status;
   pid_t pid;
@@ -102,9 +135,9 @@ fork_and_exec (const char *file,
   pid = fork ();
   if (-1 == pid)
   {
-    fprintf (stderr, 
-            "fork failed: %s\n", 
-            strerror (errno));
+    fprintf (stderr,
+             "fork failed: %s\n",
+             strerror (errno));
     return 1;
   }
   if (0 == pid)
@@ -112,24 +145,27 @@ fork_and_exec (const char *file,
     /* 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", 
-            file,
-            strerror (errno));
+    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) ); 
+  while ((-1 == (ret = waitpid (pid, &status, 0))) &&
+         (errno == EINTR))
+    ;
   if (-1 == ret)
   {
-    fprintf (stderr, 
-            "waitpid failed: %s\n", 
-            strerror (errno));
+    fprintf (stderr,
+             "waitpid failed: %s\n",
+             strerror (errno));
     return 1;
   }
   if (! (WIFEXITED (status) && (0 == WEXITSTATUS (status))))
@@ -168,10 +204,11 @@ init_tun (char *dev)
   if (fd >= FD_SETSIZE)
   {
     fprintf (stderr, "File descriptor to large: %d", fd);
+    (void) close (fd);
     return -1;
   }
 
-  memset (&ifr, 0, sizeof (ifr));
+  memset (&ifr, 0, sizeof(ifr));
   ifr.ifr_flags = IFF_TUN;
 
   if ('\0' != *dev)
@@ -179,7 +216,8 @@ init_tun (char *dev)
 
   if (-1 == ioctl (fd, TUNSETIFF, (void *) &ifr))
   {
-    fprintf (stderr, "Error with ioctl on `%s': %s\n", "/dev/net/tun",
+    fprintf (stderr,
+             "Error with ioctl on `%s': %s\n", "/dev/net/tun",
              strerror (errno));
     (void) close (fd);
     return -1;
@@ -200,16 +238,16 @@ static void
 set_address6 (const char *dev, const char *address, unsigned long prefix_len)
 {
   struct ifreq ifr;
-  struct in6_ifreq ifr6;
   struct sockaddr_in6 sa6;
   int fd;
+  struct in6_ifreq ifr6;
 
   /*
    * parse the new address
    */
-  memset (&sa6, 0, sizeof (struct sockaddr_in6));
+  memset (&sa6, 0, sizeof(struct sockaddr_in6));
   sa6.sin6_family = AF_INET6;
-  if (1 != inet_pton (AF_INET6, address, sa6.sin6_addr.s6_addr))
+  if (1 != inet_pton (AF_INET6, address, &sa6.sin6_addr))
   {
     fprintf (stderr, "Failed to parse address `%s': %s\n", address,
              strerror (errno));
@@ -222,7 +260,7 @@ set_address6 (const char *dev, const char *address, unsigned long prefix_len)
     exit (1);
   }
 
-  memset (&ifr, 0, sizeof (struct ifreq));
+  memset (&ifr, 0, sizeof(struct ifreq));
   /*
    * Get the index of the if
    */
@@ -234,7 +272,7 @@ set_address6 (const char *dev, const char *address, unsigned long prefix_len)
     exit (1);
   }
 
-  memset (&ifr6, 0, sizeof (struct in6_ifreq));
+  memset (&ifr6, 0, sizeof(struct in6_ifreq));
   ifr6.ifr6_addr = sa6.sin6_addr;
   ifr6.ifr6_ifindex = ifr.ifr_ifindex;
   ifr6.ifr6_prefixlen = prefix_len;
@@ -295,7 +333,7 @@ set_address4 (const char *dev, const char *address, const char *mask)
   struct sockaddr_in *addr;
   struct ifreq ifr;
 
-  memset (&ifr, 0, sizeof (struct ifreq));
+  memset (&ifr, 0, sizeof(struct ifreq));
   addr = (struct sockaddr_in *) &(ifr.ifr_addr);
   addr->sin_family = AF_INET;
 
@@ -414,7 +452,7 @@ run (int fd_tun)
   /* 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);
@@ -462,11 +500,13 @@ run (int fd_tun)
       if (FD_ISSET (fd_tun, &fds_r))
       {
         buftun_size =
-            read (fd_tun, buftun + sizeof (struct GNUNET_MessageHeader),
-                  MAX_SIZE - sizeof (struct GNUNET_MessageHeader));
+          read (fd_tun, buftun + sizeof(struct GNUNET_MessageHeader),
+                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;
@@ -474,7 +514,9 @@ run (int fd_tun)
         }
         else if (0 == buftun_size)
         {
+#if DEBUG
           fprintf (stderr, "EOF on tun\n");
+#endif
           shutdown (fd_tun, SHUT_RD);
           shutdown (1, SHUT_WR);
           read_open = 0;
@@ -484,8 +526,8 @@ run (int fd_tun)
         {
           buftun_read = buftun;
           struct GNUNET_MessageHeader *hdr =
-              (struct GNUNET_MessageHeader *) buftun;
-          buftun_size += sizeof (struct GNUNET_MessageHeader);
+            (struct GNUNET_MessageHeader *) buftun;
+          buftun_size += sizeof(struct GNUNET_MessageHeader);
           hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
           hdr->size = htons (buftun_size);
         }
@@ -496,7 +538,12 @@ run (int fd_tun)
 
         if (-1 == written)
         {
-          fprintf (stderr, "write-error to stdout: %s\n", strerror (errno));
+#if ! DEBUG
+          if (errno != EPIPE)
+#endif
+          fprintf (stderr,
+                   "write-error to stdout: %s\n",
+                   strerror (errno));
           shutdown (fd_tun, SHUT_RD);
           shutdown (1, SHUT_WR);
           read_open = 0;
@@ -527,7 +574,9 @@ run (int fd_tun)
         }
         else if (0 == bufin_size)
         {
+#if DEBUG
           fprintf (stderr, "EOF on stdin\n");
+#endif
           shutdown (0, SHUT_RD);
           shutdown (fd_tun, SHUT_WR);
           write_open = 0;
@@ -539,7 +588,7 @@ run (int fd_tun)
 
 PROCESS_BUFFER:
           bufin_rpos += bufin_size;
-          if (bufin_rpos < sizeof (struct GNUNET_MessageHeader))
+          if (bufin_rpos < sizeof(struct GNUNET_MessageHeader))
             continue;
           hdr = (struct GNUNET_MessageHeader *) bufin;
           if (ntohs (hdr->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER)
@@ -549,9 +598,9 @@ PROCESS_BUFFER:
           }
           if (ntohs (hdr->size) > bufin_rpos)
             continue;
-          bufin_read = bufin + sizeof (struct GNUNET_MessageHeader);
-          bufin_size = ntohs (hdr->size) - sizeof (struct GNUNET_MessageHeader);
-          bufin_rpos -= bufin_size + sizeof (struct GNUNET_MessageHeader);
+          bufin_read = bufin + sizeof(struct GNUNET_MessageHeader);
+          bufin_size = ntohs (hdr->size) - sizeof(struct GNUNET_MessageHeader);
+          bufin_rpos -= bufin_size + sizeof(struct GNUNET_MessageHeader);
         }
       }
       else if (FD_ISSET (fd_tun, &fds_w))
@@ -578,7 +627,7 @@ PROCESS_BUFFER:
           if (0 == bufin_size)
           {
             memmove (bufin, bufin_read, bufin_rpos);
-            bufin_read = NULL;  /* start reading again */
+            bufin_read = NULL;           /* start reading again */
             bufin_size = 0;
             goto PROCESS_BUFFER;
           }
@@ -593,9 +642,10 @@ PROCESS_BUFFER:
  * Open VPN tunnel interface.
  *
  * @param argc must be 6
- * @param argv 0: binary name ("gnunet-helper-vpn")
- *             1: tunnel interface name ("gnunet-vpn")
- *             2: IPv4 "physical" interface name ("eth0"), or "%" to not do IPv4 NAT
+ * @param argv 0: 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
@@ -610,36 +660,49 @@ main (int argc, char **argv)
 
   if (7 != argc)
   {
-    fprintf (stderr, "Fatal: must supply 5 arguments!\n");
+    fprintf (stderr, "Fatal: must supply 6 arguments!\n");
     return 1;
   }
-  if ( (0 == strcmp (argv[3], "-")) &&
-       (0 == strcmp (argv[5], "-")) )
+  if ((0 == strcmp (argv[3], "-")) &&
+      (0 == strcmp (argv[5], "-")))
   {
     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
-  {
-    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
+  if (0 != strcmp (argv[2], "-"))
   {
-    fprintf (stderr,
-            "Fatal: executable sysctl not found in approved directories: %s\n",
-            strerror (errno));
-    return 1;
+#ifdef IPTABLES
+    if (0 == access (IPTABLES, X_OK))
+      sbin_iptables = IPTABLES;
+    else
+#endif
+    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;
+    }
+#ifdef SYSCTL
+    if (0 == access (SYSCTL, X_OK))
+      sbin_sysctl = SYSCTL;
+    else
+#endif
+    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);
@@ -647,7 +710,13 @@ main (int argc, char **argv)
 
   if (-1 == (fd_tun = init_tun (dev)))
   {
-    fprintf (stderr, "Fatal: could not initialize tun-interface\n");
+    fprintf (stderr,
+             "Fatal: could not initialize tun-interface `%s' with IPv6 %s/%s and IPv4 %s/%s\n",
+             dev,
+             argv[3],
+             argv[4],
+             argv[5],
+             argv[6]);
     return 1;
   }
 
@@ -656,25 +725,25 @@ main (int argc, char **argv)
     {
       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);    
+        fprintf (stderr, "Fatal: prefix_len out of range\n");
+        return 1;
+      }
+      set_address6 (dev, address, prefix_len);
     }
+    if (0 != strcmp (argv[2], "-"))
     {
-      char *const sysctl_args[] =
-       {
-         "sysctl", "-w", "net.ipv6.conf.all.forwarding=1", NULL
-       };
+      char *const sysctl_args[] = {
+        "sysctl", "-w", "net.ipv6.conf.all.forwarding=1", NULL
+      };
       if (0 != fork_and_exec (sbin_sysctl,
-                             sysctl_args))
+                              sysctl_args))
       {
-       fprintf (stderr,
-                "Failed to enable IPv6 forwarding.  Will continue anyway.\n");
-      }    
+        fprintf (stderr,
+                 "Failed to enable IPv6 forwarding.  Will continue anyway.\n");
+      }
     }
   }
 
@@ -683,36 +752,37 @@ main (int argc, char **argv)
     {
       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))
@@ -738,9 +808,10 @@ main (int argc, char **argv)
   }
   run (fd_tun);
   global_ret = 0;
- cleanup:
-  close (fd_tun);
+cleanup:
+  (void) close (fd_tun);
   return global_ret;
 }
 
+
 /* end of gnunet-helper-exit.c */