provider: Set nameservers if we receive them from vpnd
[platform/upstream/connman.git] / plugins / vpn.c
index 2f3d860..d33d7c1 100644 (file)
@@ -81,6 +81,7 @@ struct connection_data {
        char **host_ip;
        char *domain;
        char **nameservers;
+       gboolean immutable;
 
        GHashTable *server_routes;
        GHashTable *user_routes;
@@ -251,6 +252,8 @@ static void set_provider_state(struct connection_data *data)
        enum connman_provider_state state = CONNMAN_PROVIDER_STATE_UNKNOWN;
        int err = 0;
 
+       DBG("provider %p new state %s", data->provider, data->state);
+
        if (g_str_equal(data->state, "ready") == TRUE) {
                state = CONNMAN_PROVIDER_STATE_READY;
                goto set;
@@ -300,6 +303,7 @@ static int create_provider(struct connection_data *data, void *user_data)
 
        err = connman_provider_create_service(data->provider);
        if (err == 0) {
+               connman_provider_set_immutable(data->provider, data->immutable);
                if (g_str_equal(data->state, "ready") == TRUE) {
                        connman_provider_set_index(data->provider,
                                                        data->index);
@@ -513,6 +517,8 @@ static int connect_provider(struct connection_data *data, void *user_data)
 
        DBG("data %p user %p path %s", data, cb_data, data->path);
 
+       data->connect_pending = FALSE;
+
        message = dbus_message_new_method_call(VPN_SERVICE, data->path,
                                        VPN_CONNECTION_INTERFACE,
                                        VPN_CONNECT);
@@ -597,6 +603,8 @@ static void add_connection(const char *path, DBusMessageIter *properties,
                } else if (g_str_equal(key, "Type") == TRUE) {
                        dbus_message_iter_get_basic(&value, &str);
                        data->type = g_strdup(str);
+               } else if (g_str_equal(key, "Immutable") == TRUE) {
+                       dbus_message_iter_get_basic(&value, &data->immutable);
                } else if (g_str_equal(key, "Host") == TRUE) {
                        dbus_message_iter_get_basic(&value, &str);
                        data->host = g_strdup(str);
@@ -607,6 +615,10 @@ static void add_connection(const char *path, DBusMessageIter *properties,
                        extract_nameservers(&value, data);
                } else if (g_str_equal(key, "Index") == TRUE) {
                        dbus_message_iter_get_basic(&value, &data->index);
+               } else if (g_str_equal(key, "ServerRoutes") == TRUE) {
+                       /* Ignored */
+               } else if (g_str_equal(key, "UserRoutes") == TRUE) {
+                       /* Ignored */
                } else {
                        if (dbus_message_iter_get_arg_type(&value) ==
                                                        DBUS_TYPE_STRING) {
@@ -631,6 +643,10 @@ static void add_connection(const char *path, DBusMessageIter *properties,
 
        resolv_host_addr(data);
 
+       if (data->nameservers != NULL)
+               connman_provider_set_nameservers(data->provider,
+                                               data->nameservers);
+
        if (data->connect_pending == TRUE)
                connect_provider(data, data->cb_data);
 
@@ -784,6 +800,14 @@ static int provider_remove(struct connman_provider *provider)
 
        DBG("provider %p data %p", provider, data);
 
+       if (data == NULL) {
+               /*
+                * This means the provider is already removed,
+                * just ignore the dbus in this case.
+                */
+               return -EALREADY;
+       }
+
        /*
         * When provider.c:provider_remove() calls this function,
         * it will remove the provider itself after the call.
@@ -1428,7 +1452,9 @@ static void destroy_provider(struct connection_data *data)
        if (data->call != NULL)
                dbus_pending_call_cancel(data->call);
 
-       connman_provider_put(data->provider);
+       connman_provider_set_data(data->provider, NULL);
+
+       connman_provider_remove(data->provider);
 
        data->provider = NULL;
 }
@@ -1486,6 +1512,7 @@ static gboolean connection_removed(DBusConnection *conn, DBusMessage *message,
 {
        const char *path;
        const char *signature = DBUS_TYPE_OBJECT_PATH_AS_STRING;
+       struct connection_data *data;
 
        if (dbus_message_has_signature(message, signature) == FALSE) {
                connman_error("vpn removed signature \"%s\" does not match "
@@ -1496,7 +1523,11 @@ static gboolean connection_removed(DBusConnection *conn, DBusMessage *message,
 
        dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
                                DBUS_TYPE_INVALID);
-       remove_connection(conn, path);
+
+       data = g_hash_table_lookup(vpn_connections, get_ident(path));
+       if (data != NULL)
+               remove_connection(conn, path);
+
        return TRUE;
 }
 
@@ -1729,7 +1760,10 @@ static gboolean property_changed(DBusConnection *conn,
                        set_routes(data->provider,
                                                CONNMAN_PROVIDER_ROUTE_USER);
        } else if (g_str_equal(key, "Nameservers") == TRUE) {
-               extract_nameservers(&value, data);
+               if (extract_nameservers(&value, data) == 0 &&
+                                               data->nameservers != NULL)
+                       connman_provider_set_nameservers(data->provider,
+                                                       data->nameservers);
        }
 
        if (ip_set == TRUE && err == 0) {