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/>.
*/
/**
#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
*/
static const char *sbin_iptables;
+/**
+ * Name and full path of IPTABLES binary.
+ */
+static const char *sbin_ip6tables;
+
/**
* Name and full path of sysctl binary
*/
return 254;
}
#endif
- if (0 == strncmp(argv[6], "1", 2))
+ if (0 == strncmp (argv[6], "1", 2))
nortsetup = 1;
if (0 == nortsetup)
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,
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[] =
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[] =
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
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
/* 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[] =
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[] =
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[] =
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[] =