fix
[oweals/gnunet.git] / src / dns / gnunet-helper-dns.c
index 2f723d09da83d0f3fa7e7a2a291fe5758305e9d1..3ed18bb7cb7b920d32f29b677965c9fc099c929b 100644 (file)
@@ -2,20 +2,18 @@
    This file is part of GNUnet.
    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.
-
-   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., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.
+   Affero General Public License for more details.
+  
+   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/>.
 */
 
 /**
@@ -79,7 +77,7 @@
 #include "gnunet_protocols.h"
 
 /**
- * Maximum size of a GNUnet message (GNUNET_SERVER_MAX_MESSAGE_SIZE)
+ * Maximum size of a GNUnet message (GNUNET_MAX_MESSAGE_SIZE)
  */
 #define MAX_SIZE 65536
 
@@ -100,6 +98,11 @@ struct in6_ifreq
  */
 static const char *sbin_iptables;
 
+/**
+ * Name and full path of IPTABLES binary.
+ */
+static const char *sbin_ip6tables;
+
 /**
  * Name and full path of sysctl binary
  */
@@ -757,7 +760,7 @@ main (int argc, char *const*argv)
     return 254;
   }
 #endif
-  if (0 == strncmp(argv[6], "1", 2))
+  if (0 == strncmp (argv[6], "1", 2))
     nortsetup = 1;
 
   if (0 == nortsetup)
@@ -774,10 +777,23 @@ main (int argc, char *const*argv)
               strerror (errno));
       return 3;
     }
+    if (0 == access ("/sbin/ip6tables", X_OK))
+      sbin_ip6tables = "/sbin/ip6tables";
+    else if (0 == access ("/usr/sbin/ip6tables", X_OK))
+      sbin_ip6tables = "/usr/sbin/ip6tables";
+    else
+    {
+      fprintf (stderr,
+              "Fatal: executable ip6tables not found in approved directories: %s\n",
+              strerror (errno));
+      return 3;
+    }
     if (0 == access ("/sbin/ip", X_OK))
       sbin_ip = "/sbin/ip";
     else if (0 == access ("/usr/sbin/ip", X_OK))
       sbin_ip = "/usr/sbin/ip";
+    else if (0 == access ("/bin/ip", X_OK)) /* gentoo has it there */
+      sbin_ip = "/bin/ip";
     else
     {
       fprintf (stderr,
@@ -942,17 +958,41 @@ main (int argc, char *const*argv)
       if (0 != fork_and_exec (sbin_iptables, mangle_args))
         goto cleanup_rest;
     }
-    /* Mark all of the other DNS traffic using our mark DNS_MARK */
+    {
+      char *const mangle_args[] =
+        {
+        "ip6tables", "-m", "owner", "-t", "mangle", "-I", "OUTPUT", "1", "-p",
+        "udp", "--gid-owner", mygid, "--dport", DNS_PORT, "-j",
+        "ACCEPT", NULL
+        };
+      if (0 != fork_and_exec (sbin_ip6tables, mangle_args))
+        goto cleanup_mangle_1b;
+    }
+    /* Mark all of the other DNS traffic using our mark DNS_MARK,
+       unless it is on a link-local IPv6 address, which we cannot support. */
     {
       char *const mark_args[] =
         {
         "iptables", "-t", "mangle", "-I", "OUTPUT", "2", "-p",
-        "udp", "--dport", DNS_PORT, "-j", "MARK", "--set-mark", DNS_MARK,
+        "udp", "--dport", DNS_PORT,
+         "-j", "MARK", "--set-mark", DNS_MARK,
         NULL
         };
       if (0 != fork_and_exec (sbin_iptables, mark_args))
         goto cleanup_mangle_1;
     }
+    {
+      char *const mark_args[] =
+        {
+        "ip6tables", "-t", "mangle", "-I", "OUTPUT", "2", "-p",
+        "udp", "--dport", DNS_PORT,
+         "!", "-s", "fe80::/10", /* this line excludes link-local traffic */
+         "-j", "MARK", "--set-mark", DNS_MARK,
+        NULL
+        };
+      if (0 != fork_and_exec (sbin_ip6tables, mark_args))
+        goto cleanup_mark_2b;
+    }
     /* Forward all marked DNS traffic to our DNS_TABLE */
     {
       char *const forward_args[] =
@@ -962,6 +1002,14 @@ main (int argc, char *const*argv)
       if (0 != fork_and_exec (sbin_ip, forward_args))
         goto cleanup_mark_2;
     }
+    {
+      char *const forward_args[] =
+        {
+          "ip", "-6", "rule", "add", "fwmark", DNS_MARK, "table", DNS_TABLE, NULL
+        };
+      if (0 != fork_and_exec (sbin_ip, forward_args))
+        goto cleanup_forward_3b;
+    }
     /* Finally, add rule in our forwarding table to pass to our virtual interface */
     {
       char *const route_args[] =
@@ -972,6 +1020,15 @@ main (int argc, char *const*argv)
       if (0 != fork_and_exec (sbin_ip, route_args))
         goto cleanup_forward_3;
     }
+    {
+      char *const route_args[] =
+        {
+          "ip", "-6", "route", "add", "default", "dev", dev,
+          "table", DNS_TABLE, NULL
+        };
+      if (0 != fork_and_exec (sbin_ip, route_args))
+        goto cleanup_route_4b;
+    }
   }
 
   /* drop privs *except* for the saved UID; this is not perfect, but better
@@ -996,7 +1053,7 @@ main (int argc, char *const*argv)
   r = 0; /* did fully setup routing table (if nothing else happens, we were successful!) */
 
   /* now forward until we hit a problem */
-   run (fd_tun);
+  run (fd_tun);
 
   /* now need to regain privs so we can remove the firewall rules we added! */
 #ifdef HAVE_SETRESUID
@@ -1018,6 +1075,17 @@ main (int argc, char *const*argv)
   /* update routing tables again -- this is why we could not fully drop privs */
   /* now undo updating of routing tables; normal exit or clean-up-on-error case */
  cleanup_route_4:
+  if (0 == nortsetup)
+  {
+    char *const route_clean_args[] =
+      {
+       "ip", "-6", "route", "del", "default", "dev", dev,
+       "table", DNS_TABLE, NULL
+      };
+    if (0 != fork_and_exec (sbin_ip, route_clean_args))
+      r += 1;
+  }
+ cleanup_route_4b:
   if (0 == nortsetup)
   {
     char *const route_clean_args[] =
@@ -1029,6 +1097,16 @@ main (int argc, char *const*argv)
       r += 1;
   }
  cleanup_forward_3:
+  if (0 == nortsetup)
+  {
+    char *const forward_clean_args[] =
+      {
+       "ip", "-6", "rule", "del", "fwmark", DNS_MARK, "table", DNS_TABLE, NULL
+      };
+    if (0 != fork_and_exec (sbin_ip, forward_clean_args))
+      r += 2;
+  }
+ cleanup_forward_3b:
   if (0 == nortsetup)
   {
     char *const forward_clean_args[] =
@@ -1039,6 +1117,19 @@ main (int argc, char *const*argv)
       r += 2;
   }
  cleanup_mark_2:
+  if (0 == nortsetup)
+  {
+    char *const mark_clean_args[] =
+      {
+       "ip6tables", "-t", "mangle", "-D", "OUTPUT", "-p", "udp",
+       "--dport", DNS_PORT,
+        "!", "-s", "fe80::/10", /* this line excludes link-local traffic */
+        "-j", "MARK", "--set-mark", DNS_MARK, NULL
+      };
+    if (0 != fork_and_exec (sbin_ip6tables, mark_clean_args))
+      r += 4;
+  }
+ cleanup_mark_2b:
   if (0 == nortsetup)
   {
     char *const mark_clean_args[] =
@@ -1050,6 +1141,18 @@ main (int argc, char *const*argv)
       r += 4;
   }
  cleanup_mangle_1:
+  if (0 == nortsetup)
+  {
+    char *const mangle_clean_args[] =
+      {
+       "ip6tables", "-m", "owner", "-t", "mangle", "-D", "OUTPUT", "-p", "udp",
+        "--gid-owner", mygid, "--dport", DNS_PORT, "-j", "ACCEPT",
+       NULL
+      };
+    if (0 != fork_and_exec (sbin_ip6tables, mangle_clean_args))
+      r += 8;
+  }
+ cleanup_mangle_1b:
   if (0 == nortsetup)
   {
     char *const mangle_clean_args[] =