char **host_ip;
char *domain;
char **nameservers;
+ gboolean immutable;
GHashTable *server_routes;
GHashTable *user_routes;
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;
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);
return 0;
}
+static int errorstr2val(const char *error) {
+ if (g_strcmp0(error, CONNMAN_ERROR_INTERFACE ".InProgress") == 0)
+ return -EINPROGRESS;
+
+ if (g_strcmp0(error, CONNMAN_ERROR_INTERFACE ".AlreadyConnected") == 0)
+ return -EISCONN;
+
+ return -ECONNREFUSED;
+}
+
static void connect_reply(DBusPendingCall *call, void *user_data)
{
DBusMessage *reply;
dbus_error_init(&error);
if (dbus_set_error_from_message(&error, reply) == TRUE) {
- if (dbus_error_has_name(&error, CONNMAN_ERROR_INTERFACE
- ".InProgress") == FALSE) {
+ int err = errorstr2val(error.name);
+ if (err != -EINPROGRESS) {
connman_error("Connect reply: %s (%s)", error.message,
error.name);
dbus_error_free(&error);
+ DBG("data %p cb_data %p", data, cb_data);
if (cb_data != NULL) {
- cb_data->callback(cb_data->message,
- ECONNREFUSED, NULL);
+ cb_data->callback(cb_data->message, err, NULL);
free_config_cb_data(cb_data);
data->cb_data = NULL;
}
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);
} 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);
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) {
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);
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.
data = g_hash_table_lookup(vpn_connections, ident);
if (data != NULL) {
- if (data->call != NULL) {
- connman_error("Dbus call already pending");
+ if (data->call != NULL || data->cb_data != NULL) {
+ DBG("create configuration call already pending");
err = -EINPROGRESS;
goto done;
}
dbus_message_set_sender(new_msg, me);
dbus_message_set_member(new_msg, "Create");
+ user_data = g_try_new0(struct config_create_data, 1);
+ if (user_data == NULL) {
+ err = -ENOMEM;
+ goto done;
+ }
+
+ user_data->callback = callback;
+ user_data->message = dbus_message_ref(msg);
+ user_data->path = NULL;
+
+ DBG("cb %p msg %p", user_data, msg);
+
result = dbus_connection_send_with_reply(connection, new_msg,
&call, DBUS_TIMEOUT);
if (result == FALSE || call == NULL) {
goto done;
}
- if (data->cb_data == NULL) {
- user_data = g_try_new(struct config_create_data, 1);
- if (user_data != NULL) {
- user_data->callback = callback;
- user_data->message = dbus_message_ref(msg);
- user_data->path = NULL;
-
- DBG("cb %p msg %p", user_data, msg);
- }
- } else {
- DBG("Configuration callback data already pending, "
- "discarding new data.");
- }
-
dbus_pending_call_set_notify(call, configuration_create_reply,
user_data, NULL);
data->call = call;
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;
}
{
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 "
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;
}
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) {