tethering: Enable NAT
authorSamuel Ortiz <sameo@linux.intel.com>
Fri, 12 Nov 2010 01:48:13 +0000 (02:48 +0100)
committerSamuel Ortiz <sameo@linux.intel.com>
Fri, 12 Nov 2010 01:48:13 +0000 (02:48 +0100)
src/tethering.c

index 208a39f..b7e9c84 100644 (file)
@@ -24,6 +24,7 @@
 #endif
 
 #include <unistd.h>
+#include <stdio.h>
 #include <sys/ioctl.h>
 #include <net/if.h>
 #include <linux/sockios.h>
@@ -35,6 +36,7 @@
 #define BRIDGE_NAME "tether"
 
 static connman_bool_t tethering_status = FALSE;
+static const char *default_interface = NULL;
 gint tethering_enabled;
 
 connman_bool_t __connman_tethering_get_status(void)
@@ -82,6 +84,50 @@ static int remove_bridge(const char *name)
        return 0;
 }
 
+static int enable_ip_forward(connman_bool_t enable)
+{
+
+       FILE *f;
+       int ip_forward = enable ? 1 : 0;
+
+       f = fopen("/proc/sys/net/ipv4/ip_forward", "r+");
+
+       fprintf(f, "%d", ip_forward);
+
+       fclose(f);
+
+       return 0;
+}
+
+static int enable_nat(const char *interface)
+{
+       int ret;
+
+       if (interface == NULL)
+               return 0;
+
+       /* Enable IPv4 forwarding */
+       ret = enable_ip_forward(TRUE);
+       if (ret < 0)
+               return ret;
+
+       /* TODO: Flush nat POSTROUTING chain */
+       /* Enable masquerading */
+       ret = __connman_iptables_command("-t nat -A POSTROUTING -o %s -j MASQUERADE", interface);
+       if (ret < 0)
+               return ret;
+
+       return __connman_iptables_commit("nat");
+}
+
+static void disable_nat(const char *interface)
+{
+       /* Disable IPv4 forwarding */
+       enable_ip_forward(FALSE);
+
+       /* TODO: Flush nat POSTROUTING chain */
+}
+
 void connman_tethering_enabled(void)
 {
        if (tethering_status == FALSE)
@@ -91,6 +137,8 @@ void connman_tethering_enabled(void)
 
        if (g_atomic_int_exchange_and_add(&tethering_enabled, 1) == 0) {
                /* TODO Start DHCP server and DNS proxy on the bridge */
+
+               enable_nat(default_interface);
                DBG("tethering started");
        }
 }
@@ -104,6 +152,8 @@ void connman_tethering_disabled(void)
 
        if (g_atomic_int_dec_and_test(&tethering_enabled) == 0) {
                /* TODO Stop DHCP server and DNS proxy on the bridge */
+
+               disable_nat(default_interface);
                DBG("tethering stopped");
        }
 }
@@ -129,6 +179,20 @@ int __connman_tethering_set_status(connman_bool_t status)
 void __connman_tethering_update_interface(const char *interface)
 {
        DBG("interface %s", interface);
+
+       default_interface = interface;
+
+       if (interface == NULL) {
+               disable_nat(interface);
+
+               return;
+       }
+
+       if (tethering_status == FALSE ||
+                       !g_atomic_int_get(&tethering_enabled))
+               return;
+
+       enable_nat(interface);
 }
 
 int __connman_tethering_init(void)