ipconfig: Add function to clear ipaddress information
[platform/upstream/connman.git] / src / tethering.c
index 265408b..f3d67df 100644 (file)
@@ -35,6 +35,7 @@
 #include <string.h>
 #include <fcntl.h>
 #include <linux/if_tun.h>
+#include <linux/if_bridge.h>
 
 #include "connman.h"
 
@@ -46,8 +47,6 @@
 #define DBUS_TYPE_UNIX_FD -1
 #endif
 
-#define BRIDGE_PROC_DIR "/proc/sys/net/bridge"
-
 #define BRIDGE_NAME "tether"
 #define BRIDGE_DNS "8.8.8.8"
 
@@ -79,9 +78,18 @@ struct connman_private_network {
 
 const char *__connman_tethering_get_bridge(void)
 {
-       struct stat st;
+       int sk, err;
+       unsigned long args[3];
+
+       sk = socket(AF_INET, SOCK_STREAM, 0);
+       if (sk < 0)
+               return NULL;
 
-       if (stat(BRIDGE_PROC_DIR, &st) < 0) {
+       args[0] = BRCTL_GET_VERSION;
+       args[1] = args[2] = 0;
+       err = ioctl(sk, SIOCGIFBR, &args);
+       close(sk);
+       if (err == -1) {
                connman_error("Missing support for 802.1d ethernet bridging");
                return NULL;
        }
@@ -190,14 +198,18 @@ void __connman_tethering_set_enabled(void)
                return;
 
        err = __connman_bridge_create(BRIDGE_NAME);
-       if (err < 0)
+       if (err < 0) {
+               __sync_fetch_and_sub(&tethering_enabled, 1);
                return;
+       }
 
        index = connman_inet_ifindex(BRIDGE_NAME);
        dhcp_ippool = __connman_ippool_create(index, 2, 252,
                                                tethering_restart, NULL);
        if (dhcp_ippool == NULL) {
                connman_error("Fail to create IP pool");
+               __connman_bridge_remove(BRIDGE_NAME);
+               __sync_fetch_and_sub(&tethering_enabled, 1);
                return;
        }
 
@@ -209,7 +221,9 @@ void __connman_tethering_set_enabled(void)
 
        err = __connman_bridge_enable(BRIDGE_NAME, gateway, broadcast);
        if (err < 0 && err != -EALREADY) {
+               __connman_ippool_unref(dhcp_ippool);
                __connman_bridge_remove(BRIDGE_NAME);
+               __sync_fetch_and_sub(&tethering_enabled, 1);
                return;
        }
 
@@ -226,7 +240,9 @@ void __connman_tethering_set_enabled(void)
                                                24 * 3600, dns);
        if (tethering_dhcp_server == NULL) {
                __connman_bridge_disable(BRIDGE_NAME);
+               __connman_ippool_unref(dhcp_ippool);
                __connman_bridge_remove(BRIDGE_NAME);
+               __sync_fetch_and_sub(&tethering_enabled, 1);
                return;
        }
 
@@ -350,7 +366,7 @@ static void remove_private_network(gpointer user_data)
        g_free(pn);
 }
 
-static void owner_disconnect(DBusConnection *connection, void *user_data)
+static void owner_disconnect(DBusConnection *conn, void *user_data)
 {
        struct connman_private_network *pn = user_data;