Updated connman to version 1.35
[platform/upstream/connman.git] / vpn / plugins / vpn.c
index 3e40e4f..f6e24c4 100755 (executable)
@@ -56,6 +56,7 @@ struct vpn_data {
        unsigned int watch;
        enum vpn_state state;
        struct connman_task *task;
+       int tun_flags;
 };
 
 struct vpn_driver_data {
@@ -89,7 +90,7 @@ static int stop_vpn(struct vpn_provider *provider)
                return 0;
 
        memset(&ifr, 0, sizeof(ifr));
-       ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
+       ifr.ifr_flags = data->tun_flags | IFF_NO_PI;
        sprintf(ifr.ifr_name, "%s", data->if_name);
 
        fd = open("/dev/net/tun", O_RDWR | O_CLOEXEC);
@@ -195,6 +196,34 @@ int vpn_set_ifname(struct vpn_provider *provider, const char *ifname)
        return 0;
 }
 
+static int vpn_set_state(struct vpn_provider *provider,
+                                               enum vpn_provider_state state)
+{
+       struct vpn_data *data = vpn_provider_get_data(provider);
+       if (!data)
+               return -EINVAL;
+
+       switch (state) {
+       case VPN_PROVIDER_STATE_UNKNOWN:
+               return -EINVAL;
+       case VPN_PROVIDER_STATE_IDLE:
+               data->state = VPN_STATE_IDLE;
+               break;
+       case VPN_PROVIDER_STATE_CONNECT:
+       case VPN_PROVIDER_STATE_READY:
+               data->state = VPN_STATE_CONNECT;
+               break;
+       case VPN_PROVIDER_STATE_DISCONNECT:
+               data->state = VPN_STATE_DISCONNECT;
+               break;
+       case VPN_PROVIDER_STATE_FAILURE:
+               data->state = VPN_STATE_FAILURE;
+               break;
+       }
+
+       return 0;
+}
+
 static void vpn_newlink(unsigned flags, unsigned change, void *user_data)
 {
        struct vpn_provider *provider = user_data;
@@ -307,17 +336,13 @@ static DBusMessage *vpn_notify(struct connman_task *task,
        return NULL;
 }
 
+#if defined TIZEN_EXT
 static void vpn_event(struct vpn_provider *provider, int state)
 {
-       struct vpn_data *data;
        struct vpn_driver_data *vpn_driver_data;
        const char *name;
-       int index, err;
-
-       data = vpn_provider_get_data(provider);
 
        name = vpn_provider_get_driver_name(provider);
-
        if (!name) {
                DBG("Cannot find VPN driver for provider %p", provider);
                vpn_provider_set_state(provider, VPN_PROVIDER_STATE_FAILURE);
@@ -335,52 +360,12 @@ static void vpn_event(struct vpn_provider *provider, int state)
 
        switch (state) {
        case VPN_STATE_CONNECT:
+               vpn_provider_set_state(provider,
+                               VPN_PROVIDER_STATE_CONNECT);
+               break;
        case VPN_STATE_READY:
-               if (data->state == VPN_STATE_READY) {
-                       /*
-                        * This is the restart case, in which case we must
-                        * just set the IP address.
-                        *
-                        * We need to remove first the old address, just
-                        * replacing the old address will not work as expected
-                        * because the old address will linger in the interface
-                        * and not disapper so the clearing is needed here.
-                        *
-                        * Also the state must change, otherwise the routes
-                        * will not be set properly.
-                        */
-                       vpn_provider_set_state(provider,
-                                               VPN_PROVIDER_STATE_CONNECT);
-
-                       vpn_provider_clear_address(provider, AF_INET);
-                       vpn_provider_clear_address(provider, AF_INET6);
-
-                       vpn_provider_change_address(provider);
-                       vpn_provider_set_state(provider,
-                                               VPN_PROVIDER_STATE_READY);
-                       break;
-               }
-
-               index = vpn_provider_get_index(provider);
-               vpn_provider_ref(provider);
-               data->watch = vpn_rtnl_add_newlink_watch(index,
-                                                    vpn_newlink, provider);
-               err = connman_inet_ifup(index);
-               if (err < 0) {
-                       if (err == -EALREADY)
-                               /*
-                                * So the interface is up already, that is just
-                                * great. Unfortunately in this case the
-                                * newlink watch might not have been called at
-                                * all. We must manually call it here so that
-                                * the provider can go to ready state and the
-                                * routes are setup properly.
-                                */
-                               vpn_newlink(IFF_UP, 0, provider);
-                       else
-                               DBG("Cannot take interface %d up err %d/%s",
-                                       index, -err, strerror(-err));
-               }
+               vpn_provider_set_state(provider,
+                               VPN_PROVIDER_STATE_READY);
                break;
 
        case VPN_STATE_UNKNOWN:
@@ -399,8 +384,9 @@ static void vpn_event(struct vpn_provider *provider, int state)
 
        return;
 }
+#endif
 
-static int vpn_create_tun(struct vpn_provider *provider)
+static int vpn_create_tun(struct vpn_provider *provider, int flags)
 {
        struct vpn_data *data = vpn_provider_get_data(provider);
        struct ifreq ifr;
@@ -420,7 +406,7 @@ static int vpn_create_tun(struct vpn_provider *provider)
        }
 
        memset(&ifr, 0, sizeof(ifr));
-       ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
+       ifr.ifr_flags = flags | IFF_NO_PI;
 
        for (i = 0; i < 256; i++) {
                sprintf(ifr.ifr_name, "vpn%d", i);
@@ -436,6 +422,7 @@ static int vpn_create_tun(struct vpn_provider *provider)
                goto exist_err;
        }
 
+       data->tun_flags = flags;
        data->if_name = (char *)g_strdup(ifr.ifr_name);
        if (!data->if_name) {
                connman_error("Failed to allocate memory");
@@ -477,7 +464,7 @@ static int vpn_connect(struct vpn_provider *provider,
        struct vpn_data *data = vpn_provider_get_data(provider);
        struct vpn_driver_data *vpn_driver_data;
        const char *name;
-       int ret = 0;
+       int ret = 0, tun_flags = IFF_TUN;
        enum vpn_state state = VPN_STATE_UNKNOWN;
 
        if (data)
@@ -525,7 +512,10 @@ static int vpn_connect(struct vpn_provider *provider,
        }
 
        if (vpn_driver_data->vpn_driver->flags != VPN_FLAG_NO_TUN) {
-               ret = vpn_create_tun(provider);
+               if (vpn_driver_data->vpn_driver->device_flags) {
+                       tun_flags = vpn_driver_data->vpn_driver->device_flags(provider);
+               }
+               ret = vpn_create_tun(provider, tun_flags);
                if (ret < 0)
                        goto exist_err;
        }
@@ -548,8 +538,10 @@ static int vpn_connect(struct vpn_provider *provider,
        }
 
 
+#if defined TIZEN_EXT
        if(vpn_driver_data->vpn_driver->set_event_cb)
                vpn_driver_data->vpn_driver->set_event_cb(vpn_event, provider);
+#endif
 
        ret = vpn_driver_data->vpn_driver->connect(provider, data->task,
                                                data->if_name, cb, dbus_sender,
@@ -669,6 +661,7 @@ int vpn_register(const char *name, struct vpn_driver *vpn_driver,
        data->provider_driver.probe = vpn_probe;
        data->provider_driver.remove = vpn_remove;
        data->provider_driver.save = vpn_save;
+       data->provider_driver.set_state = vpn_set_state;
 
        if (!driver_hash)
                driver_hash = g_hash_table_new_full(g_str_hash,