Merge "Add child SA up/down event and terminate command" into tizen accepted/tizen/unified/20170608.072306 submit/tizen/20170607.064606
authortaesub kim <taesub.kim@samsung.com>
Wed, 7 Jun 2017 06:34:12 +0000 (06:34 +0000)
committerGerrit Code Review <gerrit@review.ap-northeast-2.compute.internal>
Wed, 7 Jun 2017 06:34:12 +0000 (06:34 +0000)
packaging/connman.spec
vpn/plugins/ipsec.c
vpn/plugins/vici-client.c
vpn/plugins/vici-client.h
vpn/plugins/vpn.c

index 241b835..e653e08 100755 (executable)
@@ -5,7 +5,7 @@
 
 Name:           connman
 Version:        1.29
-Release:        22
+Release:        23
 License:        GPL-2.0+
 Summary:        Connection Manager
 Url:            http://connman.net
index b5205f7..70f3433 100644 (file)
@@ -76,9 +76,13 @@ struct openssl_private_data {
 struct ipsec_private_data {
        struct vpn_provider *provider;
        struct openssl_private_data openssl_data;
-       vpn_provider_connect_cb_t cb;
+       vpn_provider_connect_cb_t connect_cb;
+       void *connect_user_data;
+};
 
-       void *user_data;
+struct ipsec_event_data {
+       vpn_event_callback event_cb;
+       void *event_user_data;
 };
 
 struct {
@@ -162,6 +166,8 @@ static const char *ikev2_esp_proposals = "aes256-aes128-sha256-sha1";
 
 static const char *ikev2_proposals = "aes256-aes128-sha512-sha384-sha256-sha1-modp2048-modp1536-modp1024";
 
+static struct ipsec_event_data event_data;
+
 static void init_openssl(void)
 {
        /* Load the human readable error strings for libcrypto */
@@ -482,6 +488,14 @@ static int ipsec_notify(DBusMessage *msg, struct vpn_provider *provider)
        return 0;
 }
 
+static void ipsec_set_event_cb(vpn_event_callback event_cb, struct vpn_provider *provider)
+{
+       DBG("set event cb!");
+       event_data.event_cb = event_cb;
+       event_data.event_user_data = provider;
+       return;
+}
+
 static int ipsec_is_same_auth(const char* req, const char* target)
 {
        if (req == NULL || target == NULL)
@@ -869,16 +883,71 @@ static int ipsec_load_cert(struct vpn_provider *provider)
        return ret;
 }
 
-void connect_reply_cb(int err, void *user_data)
+static int ipsec_terminate(struct vpn_provider *provider)
+{
+       VICISection *sect;
+       int ret = 0;
+
+       sect = vici_create_section(NULL);
+       if (!sect)
+               return -ENOMEM;
+
+       vici_add_kv(sect, "child", "net", NULL);
+       vici_add_kv(sect, "ike", vpn_provider_get_string(provider, "Name"), NULL);
+       vici_add_kv(sect, "timeout", "-1", NULL);
+       ret = vici_send_request(vici_client, VICI_CMD_TERMINATE, sect);
+       if (ret < 0)
+               connman_error("vici_send_request failed");
+
+       vici_destroy_section(sect);
+
+       return ret;
+}
+
+static void request_reply_cb(int err, void *user_data)
 {
        struct ipsec_private_data *data;
 
        data = (struct ipsec_private_data *)user_data;
-       data->cb(data->provider, data->user_data, err);
+       DBG("request reply cb");
+
+       if(err != 0) {
+               if (event_data.event_cb)
+                       event_data.event_cb(event_data.event_user_data, VPN_STATE_FAILURE);
+               /* TODO: Does close socket needed? */
+       } else {
+               DBG("Series of requests are succeeded");
+               /* TODO: Not sure about below */
+               if (event_data.event_cb)
+                       event_data.event_cb(event_data.event_user_data, VPN_STATE_CONNECT);
+       }
 
        free_private_data(data);
 }
 
+static void ipsec_vici_event_cb(VICIClientEvent event, void *user_data)
+{
+       struct vpn_provider *provider;
+
+       provider = (struct vpn_provider *)user_data;
+       if (!provider) {
+               DBG("Invalid user data");
+               return;
+       }
+
+       if(event == VICI_EVENT_CHILD_UP) {
+               if (event_data.event_cb)
+                       event_data.event_cb(event_data.event_user_data, VPN_STATE_READY);
+       } else if (event == VICI_EVENT_CHILD_DOWN) {
+               if (event_data.event_cb)
+                       event_data.event_cb(event_data.event_user_data, VPN_STATE_DISCONNECT);
+       } else {
+               DBG("Unknown event");
+       }
+
+       return;
+}
+
 static struct ipsec_private_data* create_ipsec_private_data(struct vpn_provider *provider,
                vpn_provider_connect_cb_t cb, void* user_data)
 {
@@ -892,8 +961,8 @@ static struct ipsec_private_data* create_ipsec_private_data(struct vpn_provider
        init_openssl();
 
        data->provider = provider;
-       data->cb = cb;
-       data->user_data = user_data;
+       data->connect_cb = cb;
+       data->connect_user_data = user_data;
        return data;
 }
 
@@ -907,7 +976,7 @@ static void vici_connect(struct ipsec_private_data *data)
                IPSEC_ERROR_CHECK_GOTO(-1, done, "Invalid data parameter");
 
        provider = data->provider;
-       cb = data->cb;
+       cb = data->connect_cb;
        if (!provider || !cb)
                IPSEC_ERROR_CHECK_GOTO(-1, done, "Invalid provider or callback");
 
@@ -922,8 +991,15 @@ static void vici_connect(struct ipsec_private_data *data)
        /* TODO :remove this after debug */
        DBG("success to initialize vici socket");
 
-       vici_set_connect_reply_cb(vici_client, (vici_connect_reply_cb)connect_reply_cb, data);
+       vici_set_request_reply_cb(vici_client, (vici_request_reply_cb)request_reply_cb, data);
+       /*
+        * Sets child-updown event
+        */
+       err = vici_set_event_cb(vici_client, (vici_event_cb)ipsec_vici_event_cb, provider);
+       IPSEC_ERROR_CHECK_GOTO(err, done, "register event failed");
 
+       /* TODO :remove this after debug */
+       DBG("success to vici_set_event_cb");
        /*
         * Send the load-conn command
         */
@@ -984,8 +1060,9 @@ static void vici_connect(struct ipsec_private_data *data)
 
 done:
        /* refer to connect_cb on vpn-provider.c for cb */
-       if(err != 0 && cb)
-               cb(provider, data->user_data, -err);
+       if(cb)
+               cb(provider, data->connect_user_data, -err);
+       /* TODO: Does close socket needed? when err is not zero */
 
        return;
 }
@@ -1014,6 +1091,8 @@ static void monitor_vici_socket(struct ipsec_private_data *data)
        if (error) {
                connman_error("g_file_monitor_directory failed: %s / %d", error->message, error->code);
                g_error_free(error);
+               if(event_data.event_cb)
+                       event_data.event_cb(event_data.event_user_data, VPN_STATE_FAILURE);
                return;
        }
        /* TODO :remove this after debug */
@@ -1161,14 +1240,22 @@ static int ipsec_save(struct vpn_provider *provider, GKeyFile *keyfile)
 static void ipsec_disconnect(struct vpn_provider *provider)
 {
        int err = 0;
+       /*
+        * Send the terminate command
+        */
+       err = ipsec_terminate(provider);
+       IPSEC_ERROR_CHECK_RETURN(err, "terminate failed");
 
        err = vici_deinitialize(vici_client);
        IPSEC_ERROR_CHECK_RETURN(err, "failed to deinitialize vici_client");
+
+       return;
 }
 
 static struct vpn_driver vpn_driver = {
        .flags = VPN_FLAG_NO_TUN,
        .notify = ipsec_notify,
+       .set_event_cb = ipsec_set_event_cb,
        .connect = ipsec_connect,
        .error_code = ipsec_error_code,
        .save = ipsec_save,
@@ -1179,6 +1266,9 @@ static int ipsec_init(void)
 {
        connection = connman_dbus_get_connection();
 
+       event_data.event_cb = NULL;
+       event_data.event_user_data = NULL;
+
        return vpn_register("ipsec", &vpn_driver, IPSEC);
 }
 
index c1361e4..dc651cf 100644 (file)
@@ -68,6 +68,8 @@ static const char *vici_cmd_str[] = {
        "unload-authority",
        "load-key",
        "initiate",
+       "terminate",
+       "child-updown",
        NULL,
 };
 
@@ -89,9 +91,13 @@ struct _VICIClient {
        /* io data */
        int client_sock_fd;
        int client_watch;
+       unsigned int rcv_pkt_size;
+       char *rcvbuf;
        GSList *request_list;
-       vici_connect_reply_cb reply;
-       void *ipsec_user_data;
+       vici_request_reply_cb reply_cb;
+       vici_event_cb event_cb;
+       void *reply_user_data;
+       void *event_user_data;
 };
 
 struct _VICISection {
@@ -429,7 +435,6 @@ static void destroy_vici_request(gpointer data)
                return;
 
        g_free(req->sndbuf);
-       g_free(req->rcvbuf);
        g_free(req);
 }
 
@@ -627,27 +632,31 @@ static int write_socket(int sock, char *data, int data_len)
 int send_vici_command(struct request *req, VICIClient *vici_client)
 {
        unsigned int size = 0;
+       int sock_fd = 0;
        int res = 0;
 
-       if (req == NULL) {
+       if (req == NULL ||  vici_client == NULL) {
                connman_error("request is NULL\n");
                return -EINVAL;
        }
+       sock_fd = vici_client->client_sock_fd;
 
        size = htonl(req->used);
-       res = write_socket(vici_client->client_sock_fd, (char *)&size, sizeof(size));
+       res = write_socket(sock_fd, (char *)&size, sizeof(size));
        if (res != 0) {
                connman_error("failed to send size with network byte order\n");
                return -EIO;
        }
 
-       res = write_socket(vici_client->client_sock_fd, req->sndbuf, req->used);
+       res = write_socket(sock_fd, req->sndbuf, req->used);
        if (res != 0) {
                connman_error("failed to send pkt\n");
                return -EIO;
        }
 
-       vici_client->request_list = g_slist_append(vici_client->request_list, req);
+       if(req->cmd != VICI_CMD_REGISTER_CHILD_UPDOWN)
+               vici_client->request_list = g_slist_append(vici_client->request_list, req);
+
        return res;
 }
 
@@ -838,6 +847,9 @@ static int handle_vici_result(gboolean success, int cmd, char * err)
        case    VICI_CMD_INITIATE:
                ret = ECONNABORTED;
                break;
+       case    VICI_CMD_TERMINATE:
+               ret = EINVAL;
+               break;
        default:
                break;
        }
@@ -892,6 +904,32 @@ int vici_send_request(VICIClient *vici_client, VICIClientCmd cmd, VICISection *r
        return ret;
 }
 
+
+int vici_set_event_cb(VICIClient *vici_client, vici_event_cb cb, gpointer user_data)
+{
+       struct request *req = NULL;
+       int ret;
+
+       DBG("%s",vici_cmd_str[VICI_EVENT_CHILD_UP]);
+       ret = create_vici_request(VICI_EVENT_REGISTER, VICI_CMD_REGISTER_CHILD_UPDOWN, &req);
+       if (ret < 0) {
+               connman_error("error on create_request\n");
+               return ret;
+       }
+
+       ret = send_vici_command(req, vici_client);
+       if (ret < 0) {
+               connman_error("error on send_command\n");
+       }
+
+       destroy_vici_request(req);
+       vici_client->event_cb = cb;
+       vici_client->event_user_data = user_data;
+
+       return ret;
+
+}
+
 static int get_socket_from_source(GIOChannel *source, GIOCondition condition)
 {
        int sock = -1;
@@ -930,31 +968,32 @@ static int read_socket(int sock, char *data, unsigned int data_len)
        return total_rbytes;
 }
 
-static int recv_vici_pkt(int sock, struct request *req)
+static int recv_vici_pkt(int sock, struct _VICIClient *vici_client)
 {
-       if(!req)
+       if(!vici_client)
                return -1;
 
-       if (req->rcv_pkt_size == 0) {
+       if (vici_client->rcv_pkt_size == 0) {
                unsigned int pkt_size = 0;
                if (read_socket(sock, (char *)&pkt_size, sizeof(pkt_size)) < 0)
                        return -1;
 
-               req->rcv_pkt_size = ntohl(pkt_size);
+               vici_client->rcv_pkt_size = ntohl(pkt_size);
                /* TODO :REMOVE THIS AFTER DEBUG */
-               DBG("rcv_pkt_size [%d] will be recved\n", req->rcv_pkt_size);
+               DBG("rcv_pkt_size [%d] will be recved\n", vici_client->rcv_pkt_size);
        } else {
 
+               DBG("rcv_pkt_size [%d] is recved\n", vici_client->rcv_pkt_size);
                char *buf = NULL;
-               buf = g_try_malloc0(req->rcv_pkt_size);
+               buf = g_try_malloc0(vici_client->rcv_pkt_size);
                if (buf == NULL)
                        return -1;
 
-               if (read_socket(sock, buf, req->rcv_pkt_size) < 0) {
+               if (read_socket(sock, buf, vici_client->rcv_pkt_size) < 0) {
                        g_free(buf);
                        return -1;
                }
-               req->rcvbuf = buf;
+               vici_client->rcvbuf = buf;
        }
 
        return 0;
@@ -974,14 +1013,138 @@ static struct request *pop_vici_request(VICIClient *vici_client)
        return list->data;
 }
 
-static gboolean process_reply(GIOChannel *source,
+static void process_vici_reply(VICIClient *vici_client)
+{
+       struct request *req;
+       int ret = 0;
+
+       if (!vici_client)
+               return;
+
+       /* get first request */
+       req = pop_vici_request(vici_client);
+       if (!req)
+               return;
+
+       req->rcvbuf = vici_client->rcvbuf;
+       req->rcv_pkt_size = vici_client->rcv_pkt_size;
+
+       ret = process_vici_response(req);
+       vici_client->request_list = g_slist_remove(vici_client->request_list, req);
+       destroy_vici_request(req);
+
+       /* TODO :remove this after debug */
+       DBG("left request reply : %d", g_slist_length(vici_client->request_list));
+
+       if (ret != 0 || g_slist_length(vici_client->request_list) == 0)
+               vici_client->reply_cb(ret, vici_client->reply_user_data);
+
+}
+
+static int extract_event_name(char *buf, unsigned int size, char *temp)
+{
+       int pos = 1;
+       int name_len = 0;
+       name_len = buf[pos];
+       pos++;
+       DBG("event len: %d", name_len);
+       while(pos <  size && pos - 2 < name_len) {
+               temp[pos - 2] = buf[pos];
+               pos++;
+       }
+       temp[pos] = '\0';
+       DBG("event name: %s", temp);
+       return pos;
+}
+
+static char *vici_get_value(char *buf, unsigned int pos, unsigned int size, char *search_key)
+{
+       int type = -1;
+
+       pos = 1;
+       while (pos < size) {
+
+               type = buf[pos];//3
+               pos++;
+               if (type == VICI_KEY_VALUE) {
+                       char *key = NULL;
+                       char *value = NULL;
+                       pos = extract_key_value(buf, pos, &key, &value);
+                       if (g_strcmp0(search_key, key) == 0) {
+                               g_free(key);
+                               return value;
+                       }
+
+                       g_free(key);
+                       g_free(value);
+               }
+       }
+       return NULL;
+}
+
+static void process_child_updown(VICIClient *vici_client,char *buf, unsigned int size)
+{
+       char *state = NULL;
+
+       state = vici_get_value(buf, 0, size, "state");
+       if (g_strcmp0(state, "ESTABLISHED") == 0) {
+               DBG("ESTABLISHED");
+               vici_client->event_cb(VICI_EVENT_CHILD_UP, vici_client->event_user_data);
+       } else if (g_strcmp0(state, "DELETING") == 0) {
+               DBG("DELETING");
+               vici_client->event_cb(VICI_EVENT_CHILD_DOWN, vici_client->event_user_data);
+       } else {
+               DBG("Unknown event");
+       }
+       g_free(state);
+       return;
+}
+
+static void process_vici_event(VICIClient *vici_client)
+{
+       char *buf = NULL;
+       unsigned int size = 0;
+       unsigned int pos = 0;
+       char temp[256] = {0,};
+       if (!vici_client || !(vici_client->rcvbuf) || vici_client->rcv_pkt_size == 0)
+               return;
+
+       buf = vici_client->rcvbuf;
+       size = vici_client->rcv_pkt_size;
+
+       pos = extract_event_name(buf, size, temp);
+       /* TODO: remove below after debug */
+       /* add parser */
+       if (g_strcmp0(temp, "child-updown") == 0)
+               process_child_updown(vici_client, buf + pos -1, size - pos);
+}
+
+static void process_vici_packet(VICIClient *vici_client, char *buf)
+{
+
+       if (!vici_client || !buf)
+               return;
+
+       if (buf[0] == VICI_CMD_RESPONSE) {
+               DBG("VICI_CMD_RESPONSE\n");
+               process_vici_reply(vici_client);
+       } else if (buf[0] == VICI_EVENT_CONFIRM) {
+               DBG("VICI_EVENT_CONFIRM\n");
+       } else if (buf[0] == VICI_EVENT) {
+               DBG("VICI_EVENT");
+               process_vici_event(vici_client);
+       } else {
+               DBG("Not handled [%u]", buf[0]);
+       }
+       return;
+}
+
+static gboolean process_vici_msg(GIOChannel *source,
                                           GIOCondition condition,
                                           gpointer user_data)
 {
        VICIClient *vici_client = NULL;
-       struct request * req = NULL;
        int sock = 0;
-       int ret = 0;
 
        vici_client = (VICIClient *)user_data;
        if (!vici_client)
@@ -991,27 +1154,18 @@ static gboolean process_reply(GIOChannel *source,
        if (sock < 0)
                return FALSE;
 
-       /* get first request */
-       req = pop_vici_request((VICIClient *)user_data);
-       if (!req)
-               return FALSE;
 
-       if(recv_vici_pkt(sock, req) < 0)
+       if(recv_vici_pkt(sock, vici_client) < 0)
                return FALSE;
 
-       if (!req->rcvbuf) {
+       if (!vici_client->rcvbuf) {
                return TRUE;
        }
 
-       ret = process_vici_response(req);
-       vici_client->request_list = g_slist_remove(vici_client->request_list, req);
-       destroy_vici_request(req);
-
-       /* TODO :remove this after debug */
-       DBG("left request reply : %d", g_slist_length(vici_client->request_list));
-
-       if (ret!= 0 || g_slist_length(vici_client->request_list) == 0)
-               vici_client->reply(ret, vici_client->ipsec_user_data);
+       process_vici_packet(vici_client, vici_client->rcvbuf);
+       g_free(vici_client->rcvbuf);
+       vici_client->rcvbuf = NULL;
+       vici_client->rcv_pkt_size = 0;
 
        return TRUE;
 }
@@ -1054,47 +1208,60 @@ static int connect_socket(const char *uri)
        return fd;
 }
 
-int vici_initialize(VICIClient **vici_client)
+static int initialize_vici_source(VICIClient *vici_client)
 {
        GIOChannel *vici_channel;
-
-       *vici_client = g_try_new0(VICIClient, 1);
-       if (!*vici_client) {
-               connman_error("out of memory");
+       if (!vici_client) {
                return -ENOMEM;
        }
 
-       (*vici_client)->client_sock_fd = connect_socket(VICI_DEFAULT_URI);
-       if ((*vici_client)->client_sock_fd < 0) {
+       vici_client->client_sock_fd = connect_socket(VICI_DEFAULT_URI);
+       if (vici_client->client_sock_fd < 0) {
                connman_error("connect_socket failed");
-               g_free(*vici_client);
                return -EIO;
        }
 
-       vici_channel = g_io_channel_unix_new((*vici_client)->client_sock_fd);
+       vici_channel = g_io_channel_unix_new(vici_client->client_sock_fd);
        if (!vici_channel) {
                connman_error("g_io_channel_unix_new failed");
-               close((*vici_client)->client_sock_fd);
-               g_free(*vici_client);
+               close(vici_client->client_sock_fd);
                return -ENOMEM;
        }
 
-       (*vici_client)->client_watch = g_io_add_watch_full(vici_channel,
+       vici_client->client_watch = g_io_add_watch_full(vici_channel,
                                                 G_PRIORITY_LOW,
                                                 G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
-                                                (GIOFunc)process_reply,
-                                                (gpointer)*vici_client,
+                                                (GIOFunc)process_vici_msg,
+                                                (gpointer)vici_client,
                                                 NULL);
        g_io_channel_unref(vici_channel);
+       return 0;
+}
+
+int vici_initialize(VICIClient **vici_client)
+{
+       int ret = 0;
+
+       *vici_client = g_try_new0(VICIClient, 1);
+       if (!*vici_client) {
+               connman_error("out of memory");
+               return -ENOMEM;
+       }
+
+       ret = initialize_vici_source(*vici_client);
+       if (ret != 0) {
+               g_free(*vici_client);
+               return ret;
+       }
 
        DBG("connected");
        return 0;
 }
 
-void vici_set_connect_reply_cb(VICIClient *vici_client, vici_connect_reply_cb reply_cb, gpointer user_data)
+void vici_set_request_reply_cb(VICIClient *vici_client, vici_request_reply_cb reply_cb, gpointer user_data)
 {
-       vici_client->reply = reply_cb;
-       vici_client->ipsec_user_data = user_data;
+       vici_client->reply_cb = reply_cb;
+       vici_client->reply_user_data = user_data;
 }
 
 int vici_deinitialize(VICIClient *vici_client)
@@ -1106,6 +1273,7 @@ int vici_deinitialize(VICIClient *vici_client)
 
        close(vici_client->client_sock_fd);
        g_slist_free_full(vici_client->request_list, destroy_vici_request);
+       g_free(vici_client->rcvbuf);
        g_free(vici_client);
 
        return 0;
index 9d08d7d..a33a8e4 100644 (file)
@@ -39,15 +39,23 @@ typedef enum {
        VICI_CMD_UNLOAD_AUTH,
        VICI_CMD_LOAD_KEY,
        VICI_CMD_INITIATE,
+       VICI_CMD_TERMINATE,
+       VICI_CMD_REGISTER_CHILD_UPDOWN,
        VICI_CMD_MAX,
 } VICIClientCmd;
 
+typedef enum {
+       VICI_EVENT_CHILD_UP,
+       VICI_EVENT_CHILD_DOWN,
+       VICI_EVENT_MAX,
+} VICIClientEvent;
 #define VICI_DEFAULT_URI "/var/run/charon.vici"
 
 typedef int (*vici_add_element)(VICISection *sect, const char *key,
                const char *value, const char *subsection);
 
-typedef void (*vici_connect_reply_cb)(int err, void *user_data);
+typedef void (*vici_request_reply_cb)(int err, void *user_data);
+typedef void (*vici_event_cb)(VICIClientEvent event, void *user_data);
 
 VICISection* vici_create_section(const char *name);
 int add_subsection(const char* name, VICISection* child, VICISection* section);
@@ -65,8 +73,9 @@ int vici_add_cert_kvl(VICISection *section, const char *key,
 
 int vici_initialize(VICIClient **vici_client);
 int vici_deinitialize(VICIClient *vici_client);
-void vici_set_connect_reply_cb(VICIClient *vici_client, vici_connect_reply_cb reply_cb, gpointer user_data);
+void vici_set_request_reply_cb(VICIClient *vici_client, vici_request_reply_cb reply_cb, gpointer user_data);
 int vici_send_request(VICIClient *vici_client, VICIClientCmd cmd, VICISection *root);
+int vici_set_event_cb(VICIClient *vici_client, vici_event_cb cb, gpointer user_data);
 
 #ifdef __cplusplus
 }
index b48b6bc..e65daca 100755 (executable)
@@ -310,15 +310,10 @@ static DBusMessage *vpn_notify(struct connman_task *task,
 #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);
@@ -336,52 +331,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: