fix
[oweals/gnunet.git] / src / vpn / gnunet-helper-hijack-dns.c
index 7add2cc3e4c4a577482c6f967654f0c3fc35330f..ee7ae18738d88e2208edfc670fabe413bb8f63db 100644 (file)
  * @brief
  * @author Philipp Tölke
  */
-#define _GNU_SOURCE
+#include <platform.h>
 
-#include <arpa/inet.h>
-
-#include <string.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <gnunet_common.h>
+#include "gnunet_common.h"
 
 int fork_and_exec(char* file, char* cmd[]) {
        pid_t pid = fork();
        if (pid < 0) {
-               fprintf(stderr, "could not fork: %m\n");
+               fprintf(stderr, "could not fork: %s\n", strerror(errno));
                return GNUNET_SYSERR;
        }
 
@@ -57,21 +47,28 @@ int fork_and_exec(char* file, char* cmd[]) {
 int main(int argc, char** argv) {
        int delete = 0;
        int port = 0;
-       if (argc < 2) return GNUNET_SYSERR;
+        char* virt_dns;
+       if (argc < 3) return GNUNET_SYSERR;
 
        if (strncmp(argv[1], "-d", 2) == 0) {
                if (argc < 3) return GNUNET_SYSERR;
                delete = 1;
                port = atoi(argv[2]);
+                virt_dns = argv[3];
        } else {
                port = atoi(argv[1]);
+                virt_dns = argv[2];
        }
 
        if (port == 0) return GNUNET_SYSERR;
 
        struct stat s;
        if (stat("/sbin/iptables", &s) < 0) {
-               fprintf(stderr, "stat on /sbin/iptables failed: %m\n");
+               fprintf(stderr, "stat on /sbin/iptables failed: %s\n", strerror(errno));
+               return GNUNET_SYSERR;
+       }
+       if (stat("/sbin/ip", &s) < 0) {
+               fprintf(stderr, "stat on /sbin/ip failed: %s\n", strerror(errno));
                return GNUNET_SYSERR;
        }
 
@@ -80,11 +77,24 @@ int main(int argc, char** argv) {
 
        int r;
        if (delete) {
-               r = fork_and_exec("/sbin/iptables", (char*[]){"iptables", "-t", "nat", "-D", "OUTPUT", "-p", "udp", "--sport", localport, "--dport", "53", "-j", "ACCEPT", NULL});
-               r = fork_and_exec("/sbin/iptables", (char*[]){"iptables", "-t", "nat", "-D", "OUTPUT", "-p", "udp", "--dport", "53", "-j", "DNAT", "--to-destination", "10.10.10.2:53", NULL});
+e4:
+               r = fork_and_exec("/sbin/ip", (char*[]){"ip", "route", "del", "default", "via", virt_dns,"table","2", NULL});
+e3:
+               r = fork_and_exec("/sbin/ip", (char*[]){"ip", "rule", "del", "fwmark", "3", "table","2", NULL});
+e2:
+               r = fork_and_exec("/sbin/iptables", (char*[]){"iptables", "-t", "mangle", "-D", "OUTPUT", "-p", "udp", "--dport", "53", "-j", "MARK", "--set-mark", "3", NULL});
+e1:
+               r = fork_and_exec("/sbin/iptables", (char*[]){"iptables", "-t", "mangle", "-D", "OUTPUT", "-p", "udp", "--sport", localport, "--dport", "53", "-j", "ACCEPT", NULL});
+               if (!delete) r = 0;
        } else {
-               r = fork_and_exec("/sbin/iptables", (char*[]){"iptables", "-t", "nat", "-I", "OUTPUT", "1", "-p", "udp", "--sport", localport, "--dport", "53", "-j", "ACCEPT", NULL});
-               r = fork_and_exec("/sbin/iptables", (char*[]){"iptables", "-t", "nat", "-I", "OUTPUT", "2", "-p", "udp", "--dport", "53", "-j", "DNAT", "--to-destination", "10.10.10.2:53", NULL});
+               r = fork_and_exec("/sbin/iptables", (char*[]){"iptables", "-t", "mangle", "-I", "OUTPUT", "1", "-p", "udp", "--sport", localport, "--dport", "53", "-j", "ACCEPT", NULL});
+               if (!r) goto e1;
+               r = fork_and_exec("/sbin/iptables", (char*[]){"iptables", "-t", "mangle", "-I", "OUTPUT", "2", "-p", "udp", "--dport", "53", "-j", "MARK", "--set-mark", "3", NULL});
+               if (!r) goto e2;
+               r = fork_and_exec("/sbin/ip", (char*[]){"ip", "rule", "add", "fwmark", "3", "table","2", NULL});
+               if (!r) goto e3;
+               r = fork_and_exec("/sbin/ip", (char*[]){"ip", "route", "add", "default", "via", virt_dns, "table","2", NULL});
+               if (!r) goto e4;
        }
        if (r) return GNUNET_YES;
        return GNUNET_SYSERR;