static void
test_make_invisible (void)
{
	time_t start, now;
	GSList *list, *iter;
	DBusGProxy *proxy;
	gboolean done = FALSE, has_settings = FALSE;
	char *path;

	g_assert (remote != NULL);

	/* Listen for the remove event when the connection becomes invisible */
	g_signal_connect (remote, "removed", G_CALLBACK (invis_removed_cb), &done);

	path = g_strdup (nm_connection_get_path (NM_CONNECTION (remote)));
	proxy = dbus_g_proxy_new_for_name (bus,
	                                   NM_DBUS_SERVICE,
	                                   path,
	                                   NM_DBUS_IFACE_SETTINGS_CONNECTION);
	g_assert (proxy != NULL);

	/* Bypass the NMRemoteSettings object so we can test it independently */
	dbus_g_proxy_begin_call (proxy, "SetVisible", set_visible_cb, NULL, NULL,
	                         G_TYPE_BOOLEAN, FALSE, G_TYPE_INVALID);

	/* Wait for the connection to be removed */
	start = time (NULL);
	do {
		now = time (NULL);
		g_main_context_iteration (NULL, FALSE);
	} while ((done == FALSE) && (now - start < 5));
	g_assert (done == TRUE);

	g_assert (remote);
	g_signal_handlers_disconnect_by_func (remote, G_CALLBACK (invis_removed_cb), &done);

	/* Ensure NMRemoteSettings no longer has the connection */
	list = nm_remote_settings_list_connections (settings);
	for (iter = list; iter; iter = g_slist_next (iter)) {
		NMConnection *candidate = NM_CONNECTION (iter->data);

		g_assert ((gpointer) remote != (gpointer) candidate);
		g_assert (strcmp (path, nm_connection_get_path (candidate)) != 0);
	}

	/* And ensure the invisible connection no longer has any settings */
	g_assert (remote);
	nm_connection_for_each_setting_value (NM_CONNECTION (remote),
	                                      invis_has_settings_cb,
	                                      &has_settings);
	g_assert (has_settings == FALSE);

	g_free (path);
	g_object_unref (proxy);
}
/* Print details of connection */
static void
show_connection (NMConnection *connection)
{
	NMSettingConnection *s_con;
	guint64 timestamp;
	char *timestamp_str;
	char timestamp_real_str[64];
	const char *val1, *val2, *val3, *val3a, *val4, *val5;

	s_con = nm_connection_get_setting_connection (connection);
	if (s_con) {
		/* Get various info from NMSettingConnection and show it */
		timestamp = nm_setting_connection_get_timestamp (s_con);
		timestamp_str = g_strdup_printf ("%" G_GUINT64_FORMAT, timestamp);
		strftime (timestamp_real_str, sizeof (timestamp_real_str), "%c", localtime ((time_t *) &timestamp));

		val1 = nm_setting_connection_get_id (s_con);
		val2 = nm_setting_connection_get_uuid (s_con);
		val3 = nm_setting_connection_get_connection_type (s_con);
		val3a = nm_setting_connection_get_interface_name (s_con);
		val4 = nm_connection_get_path (connection);
		val5 = timestamp ? timestamp_real_str : "never";

		printf ("%-25s | %s | %-15s | %10s | %-43s | %s\n", val1, val2, val3, val3a, val4, val5);

		g_free (timestamp_str);
	}
}
예제 #3
0
static void
added_cb (GObject *client,
          GAsyncResult *result,
          gpointer user_data)
{
	GMainLoop *loop = user_data;
	NMRemoteConnection *remote;
	GError *error;

	/* NM responded to our request; either handle the resulting error or
	 * print out the object path of the connection we just added.
	 */
	remote = nm_client_add_connection_finish (NM_CLIENT (client), result, &error);

	if (error) {
		g_print ("Error adding connection: %s", error->message);
		g_error_free (error);
	} else {
		g_print ("Added: %s\n", nm_connection_get_path (NM_CONNECTION (remote)));
		g_object_unref (remote);
	}

	/* Tell the mainloop we're done and we can quit now */
	g_main_loop_quit (loop);
}
예제 #4
0
static NMConnection *
get_connection_for_active (NMApplet *applet, NMActiveConnection *active)
{
	GSList *list, *iter;
	NMConnection *connection = NULL;
	NMConnectionScope scope;
	const char *path;

	scope = nm_active_connection_get_scope (active);
	g_return_val_if_fail (scope != NM_CONNECTION_SCOPE_UNKNOWN, NULL);

	path = nm_active_connection_get_connection (active);
	g_return_val_if_fail (path != NULL, NULL);

	list = applet_get_all_connections (applet);
	for (iter = list; iter; iter = g_slist_next (iter)) {
		NMConnection *candidate = NM_CONNECTION (iter->data);

		if (   (nm_connection_get_scope (candidate) == scope)
			   && !strcmp (nm_connection_get_path (candidate), path)) {
			connection = candidate;
			break;
		}
	}

	g_slist_free (list);

	return connection;
}
static gpointer
agent_new_save_delete (NMSecretAgent *self,
                       NMConnection *connection,
                       NMConnectionSerializationFlags flags,
                       const char *method,
                       NMSecretAgentCallback callback,
                       gpointer callback_data)
{
	NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self);
	GVariant *dict;
	GHashTable *hash;
	Request *r;
	const char *cpath = nm_connection_get_path (connection);

	dict = nm_connection_to_dbus (connection, flags);
	hash = nm_utils_connection_dict_to_hash (dict);
	g_variant_unref (dict);

	r = request_new (self, cpath, NULL, callback, callback_data);
	r->call = dbus_g_proxy_begin_call_with_timeout (priv->proxy,
	                                                method,
	                                                agent_save_delete_cb,
	                                                r,
	                                                NULL,
	                                                10000, /* 10 seconds */
	                                                DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, hash,
	                                                DBUS_TYPE_G_OBJECT_PATH, cpath,
	                                                G_TYPE_INVALID);
	g_hash_table_insert (priv->requests, r->call, r);

	g_hash_table_destroy (hash);
	return r->call;
}
gconstpointer
nm_secret_agent_get_secrets (NMSecretAgent *self,
                             NMConnection *connection,
                             const char *setting_name,
                             const char **hints,
                             NMSecretAgentGetSecretsFlags flags,
                             NMSecretAgentCallback callback,
                             gpointer callback_data)
{
	NMSecretAgentPrivate *priv;
	GVariant *dict;
	GHashTable *hash;
	Request *r;

	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (connection != NULL, NULL);
	g_return_val_if_fail (setting_name != NULL, NULL);

	priv = NM_SECRET_AGENT_GET_PRIVATE (self);
	g_return_val_if_fail (priv->proxy != NULL, NULL);

	dict = nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL);
	hash = nm_utils_connection_dict_to_hash (dict);
	g_variant_unref (dict);

	/* Mask off the private flags if present */
	flags &= ~NM_SECRET_AGENT_GET_SECRETS_FLAG_ONLY_SYSTEM;
	flags &= ~NM_SECRET_AGENT_GET_SECRETS_FLAG_NO_ERRORS;

	r = request_new (self, nm_connection_get_path (connection), setting_name, callback, callback_data);
	r->call = dbus_g_proxy_begin_call_with_timeout (priv->proxy,
	                                                "GetSecrets",
	                                                get_callback,
	                                                r,
	                                                NULL,
	                                                120000, /* 120 seconds */
	                                                DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, hash,
	                                                DBUS_TYPE_G_OBJECT_PATH, nm_connection_get_path (connection),
	                                                G_TYPE_STRING, setting_name,
	                                                G_TYPE_STRV, hints,
	                                                G_TYPE_UINT, flags,
	                                                G_TYPE_INVALID);
	g_hash_table_insert (priv->requests, r->call, r);

	g_hash_table_destroy (hash);
	return r->call;
}
예제 #7
0
static void
impl_ifcfgrh_get_ifcfg_details (SettingsPluginIfcfg *plugin,
                                GDBusMethodInvocation *context,
                                const char *in_ifcfg)
{
	NMIfcfgConnection *connection;
	NMSettingConnection *s_con;
	const char *uuid;
	const char *path;

	if (!g_path_is_absolute (in_ifcfg)) {
		g_dbus_method_invocation_return_error (context,
		                                       NM_SETTINGS_ERROR,
		                                       NM_SETTINGS_ERROR_INVALID_CONNECTION,
		                                       "ifcfg path '%s' is not absolute", in_ifcfg);
		return;
	}

	connection = find_by_path (plugin, in_ifcfg);
	if (   !connection
	    || nm_ifcfg_connection_get_unmanaged_spec (connection)
	    || nm_ifcfg_connection_get_unrecognized_spec (connection)) {
		g_dbus_method_invocation_return_error (context,
		                                       NM_SETTINGS_ERROR,
		                                       NM_SETTINGS_ERROR_INVALID_CONNECTION,
		                                       "ifcfg file '%s' unknown", in_ifcfg);
		return;
	}

	s_con = nm_connection_get_setting_connection (NM_CONNECTION (connection));
	if (!s_con) {
		g_dbus_method_invocation_return_error (context,
		                                       NM_SETTINGS_ERROR,
		                                       NM_SETTINGS_ERROR_FAILED,
		                                       "unable to retrieve the connection setting");
		return;
	}

	uuid = nm_setting_connection_get_uuid (s_con);
	if (!uuid) {
		g_dbus_method_invocation_return_error (context,
		                                       NM_SETTINGS_ERROR,
		                                       NM_SETTINGS_ERROR_FAILED,
		                                       "unable to get the UUID");
		return;
	}

	path = nm_connection_get_path (NM_CONNECTION (connection));
	if (!path) {
		g_dbus_method_invocation_return_error (context,
		                                       NM_SETTINGS_ERROR,
		                                       NM_SETTINGS_ERROR_FAILED,
		                                       "unable to get the connection D-Bus path");
		return;
	}

	g_dbus_method_invocation_return_value (context,
	                                       g_variant_new ("(so)", uuid, path));
}
예제 #8
0
gconstpointer
nm_secret_agent_get_secrets (NMSecretAgent *self,
                             NMConnection *connection,
                             const char *setting_name,
                             const char *hint,
                             NMSettingsGetSecretsFlags flags,
                             NMSecretAgentCallback callback,
                             gpointer callback_data)
{
    NMSecretAgentPrivate *priv;
    GHashTable *hash;
    const char *hints[2] = { hint, NULL };
    Request *r;

    g_return_val_if_fail (self != NULL, NULL);
    g_return_val_if_fail (connection != NULL, NULL);
    g_return_val_if_fail (setting_name != NULL, NULL);

    priv = NM_SECRET_AGENT_GET_PRIVATE (self);

    hash = nm_connection_to_hash (connection, NM_SETTING_HASH_FLAG_ALL);

    /* Mask off the private ONLY_SYSTEM flag if present */
    flags &= ~NM_SETTINGS_GET_SECRETS_FLAG_ONLY_SYSTEM;

    r = request_new (self, nm_connection_get_path (connection), setting_name, callback, callback_data);
    r->call = dbus_g_proxy_begin_call_with_timeout (priv->proxy,
              "GetSecrets",
              get_callback,
              r,
              NULL,
              120000, /* 120 seconds */
              DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, hash,
              DBUS_TYPE_G_OBJECT_PATH, nm_connection_get_path (connection),
              G_TYPE_STRING, setting_name,
              G_TYPE_STRV, hints,
              G_TYPE_UINT, flags,
              G_TYPE_INVALID);
    g_hash_table_insert (priv->requests, r->call, r);

    g_hash_table_destroy (hash);
    return r->call;
}
static void
connection_removed_cb (NMRemoteConnection *remote, gpointer user_data)
{
	NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
	NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
	const char *path;

	path = nm_connection_get_path (NM_CONNECTION (remote));
	g_hash_table_remove (priv->connections, path);
	g_hash_table_remove (priv->pending, path);
}
static void
connection_init_result_cb (NMRemoteConnection *remote,
                           GParamSpec *pspec,
                           gpointer user_data)
{
	NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
	NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
	guint32 init_result = NM_REMOTE_CONNECTION_INIT_RESULT_UNKNOWN;
	const char *path;

	/* Disconnect from the init-result signal just to be safe */
	g_signal_handlers_disconnect_matched (remote,
	                                      G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
	                                      0,
	                                      0,
	                                      NULL,
	                                      G_CALLBACK (connection_init_result_cb),
	                                      self);

	path = nm_connection_get_path (NM_CONNECTION (remote));

	g_object_get (G_OBJECT (remote),
	              NM_REMOTE_CONNECTION_INIT_RESULT, &init_result,
	              NULL);

	switch (init_result) {
	case NM_REMOTE_CONNECTION_INIT_RESULT_SUCCESS:
		/* ref it when adding to ->connections, since removing it from ->pending
		 * will unref it.
		 */
		g_hash_table_insert (priv->connections, g_strdup (path), g_object_ref (remote));

		/* Finally, let users know of the new connection now that it has all
		 * its settings and is valid.
		 */
		g_signal_emit_by_name (self, "new-connection", remote);
		break;
	case NM_REMOTE_CONNECTION_INIT_RESULT_ERROR:
	default:
		break;
	}

	g_hash_table_remove (priv->pending, path);

	/* Let listeners know that all connections have been found */
	if (!g_hash_table_size (priv->pending))
		g_signal_emit_by_name (self, NM_SETTINGS_INTERFACE_CONNECTIONS_READ);
}
static gboolean
impl_settings_list_connections (NMSettingsService *self,
                                GPtrArray **connections,
                                GError **error)
{
	GSList *list = NULL, *iter;

	list = list_connections (NM_SETTINGS_INTERFACE (self));
	*connections = g_ptr_array_sized_new (g_slist_length (list) + 1);
	for (iter = list; iter; iter = g_slist_next (iter)) {
		g_ptr_array_add (*connections,
		                 g_strdup (nm_connection_get_path (NM_CONNECTION (iter->data))));
	}
	g_slist_free (list);
	return TRUE;
}
예제 #12
0
/*
 * nmc_find_connection:
 * @connections: array of NMConnections to search in
 * @filter_type: "id", "uuid", "path" or %NULL
 * @filter_val: connection to find (connection name, UUID or path)
 * @start: where to start in @list. The location is updated so that the function
 *   can be called multiple times (for connections with the same name).
 *
 * Find a connection in @list according to @filter_val. @filter_type determines
 * what property is used for comparison. When @filter_type is NULL, compare
 * @filter_val against all types. Otherwise, only compare against the specified
 * type. If 'path' filter type is specified, comparison against numeric index
 * (in addition to the whole path) is allowed.
 *
 * Returns: found connection, or %NULL
 */
NMConnection *
nmc_find_connection (const GPtrArray *connections,
                     const char *filter_type,
                     const char *filter_val,
                     int *start)
{
	NMConnection *connection;
	NMConnection *found = NULL;
	int i;
	const char *id;
	const char *uuid;
	const char *path, *path_num;

	for (i = start ? *start : 0; i < connections->len; i++) {
		connection = NM_CONNECTION (connections->pdata[i]);

		id = nm_connection_get_id (connection);
		uuid = nm_connection_get_uuid (connection);
		path = nm_connection_get_path (connection);
		path_num = path ? strrchr (path, '/') + 1 : NULL;

		/* When filter_type is NULL, compare connection ID (filter_val)
		 * against all types. Otherwise, only compare against the specific
		 * type. If 'path' filter type is specified, comparison against
		 * numeric index (in addition to the whole path) is allowed.
		 */
		if (   (   (!filter_type || strcmp (filter_type, "id")  == 0)
		        && strcmp (filter_val, id) == 0)
		    || (   (!filter_type || strcmp (filter_type, "uuid") == 0)
		        && strcmp (filter_val, uuid) == 0)
		    || (   (!filter_type || strcmp (filter_type, "path") == 0)
		        && (g_strcmp0 (filter_val, path) == 0 || (filter_type && g_strcmp0 (filter_val, path_num) == 0)))) {
			if (!start)
				return connection;
			if (found) {
				*start = i;
				return found;
			}
			found = connection;
		}
	}

	if (start)
		*start = 0;
	return found;
}
static NMSettingsConnectionInterface *
get_connection_by_path (NMSettingsInterface *settings, const char *path)
{
	NMExportedConnection *connection = NULL;
	GSList *list = NULL, *iter;

	list = list_connections (settings);
	for (iter = list; iter; iter = g_slist_next (iter)) {
		if (!strcmp (nm_connection_get_path (NM_CONNECTION (iter->data)), path)) {
			connection = NM_EXPORTED_CONNECTION (iter->data);
			break;
		}
	}
	g_slist_free (list);

	return (NMSettingsConnectionInterface *) connection;
}
static void
connections_read (NMSettingsInterface *settings, gpointer user_data)
{
	GSList *connections;
	NMConnection *connection;
	NMDevice *dev;
	struct start_network_data *data = (struct start_network_data *)user_data;
	static int tries = 0;

	if(!NM_IS_REMOTE_SETTINGS_SYSTEM(settings))
	{
		network_status (data->client, "Not a settings_system object!  Huh?\n");
		g_main_loop_quit (loop);
		return;
	}

	connections = nm_settings_interface_list_connections (settings);
	connection = find_connection(connections, data->uuid);

	if (!connection) {
		if (tries++ >= 2) {
			network_status (data->client, "Unable to find connection from " NETWORK_CONFIG " in system configs file");
			g_main_loop_quit(loop);
			return;
		}
		return;
	}

	dev = get_device_for_connection (data->client, connection);
	if (!dev) {
		network_status (data->client, "Unable to find correct device for connection");
		g_main_loop_quit(loop);
		return;
	}
	data->should_quit = FALSE;

	nm_client_activate_connection (data->client,
					NM_DBUS_SERVICE_SYSTEM_SETTINGS,
					nm_connection_get_path (connection),//con_path,
					dev,//device,
					NULL,//spec_object,
					activate_connection_cb,
					data);
	return;
}
static NMActiveConnection *
connection_find_ac (NMConnection    *conn,
                    const GPtrArray *acs)
{
	NMActiveConnection *ac;
	const char *path, *ac_path;
	int i;

	path = nm_connection_get_path (conn);
	for (i = 0; acs && i < acs->len; i++) {
		ac = acs->pdata[i];
		ac_path = nm_active_connection_get_connection (ac);

		if (!g_strcmp0 (path, ac_path))
			return ac;
	}

	return NULL;
}
static void
get_property (GObject *object, guint prop_id,
			  GValue *value, GParamSpec *pspec)
{
	NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (object);
	GPtrArray *devices;

	switch (prop_id) {
	case PROP_SERVICE_NAME:
		nm_active_connection_scope_to_value (priv->connection, value);
		break;
	case PROP_CONNECTION:
		g_value_set_boxed (value, nm_connection_get_path (priv->connection));
		break;
	case PROP_SPECIFIC_OBJECT:
		if (priv->specific_object)
			g_value_set_boxed (value, priv->specific_object);
		else
			g_value_set_boxed (value, "/");
		break;
	case PROP_DEVICES:
		devices = g_ptr_array_sized_new (1);
		g_ptr_array_add (devices, g_strdup (nm_device_get_path (priv->device)));
		g_value_take_boxed (value, devices);
		break;
	case PROP_STATE:
		g_value_set_uint (value, priv->state);
		break;
	case PROP_DEFAULT:
		g_value_set_boolean (value, priv->is_default);
		break;
	case PROP_DEFAULT6:
		g_value_set_boolean (value, priv->is_default6);
		break;
	case PROP_VPN:
		g_value_set_boolean (value, FALSE);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}
static void
added_cb (NMRemoteSettings *settings,
          NMRemoteConnection *remote,
          GError *error,
          gpointer user_data)
{
	GMainLoop *loop = user_data;

	/* NM responded to our request; either handle the resulting error or
	 * print out the object path of the connection we just added.
	 */

	if (error)
		g_print ("Error adding connection: %s", error->message);
	else
		g_print ("Added: %s\n", nm_connection_get_path (NM_CONNECTION (remote)));

	/* Tell the mainloop we're done and we can quit now */
	g_main_loop_quit (loop);
}
예제 #18
0
static void
connection_visible_cb (NMRemoteConnection *remote,
                       gboolean visible,
                       gpointer user_data)
{
	NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
	NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
	const char *path;

	path = nm_connection_get_path (NM_CONNECTION (remote));
	g_assert (path);

	/* When a connection becomes invisible, we put it back in the pending
	 * hash until it becomes visible again.  When it does, we move it back to
	 * the normal connections hash.
	 */
	if (visible) {
		/* Connection visible to this user again */
		if (g_hash_table_lookup (priv->pending, path)) {
			/* Move connection from pending to visible hash; emit for clients */
			g_hash_table_insert (priv->connections, g_strdup (path), g_object_ref (remote));
			g_hash_table_remove (priv->pending, path);
			g_signal_emit (self, signals[NEW_CONNECTION], 0, remote);
		}
	} else {
		/* Connection now invisible to this user */
		if (g_hash_table_lookup (priv->connections, path)) {
			/* Move connection to pending hash and wait for it to become visible again */
			g_hash_table_insert (priv->pending, g_strdup (path), g_object_ref (remote));
			g_hash_table_remove (priv->connections, path);

			/* Signal to clients that the connection is gone; but we have to
			 * block our connection removed handler so we don't destroy
			 * the connection when the signal is emitted.
			 */
			g_signal_handlers_block_by_func (remote, connection_removed_cb, self);
			g_signal_emit_by_name (remote, NM_REMOTE_CONNECTION_REMOVED);
			g_signal_handlers_unblock_by_func (remote, connection_removed_cb, self);
		}
	}
}
static void
get_property (GObject *object, guint prop_id,
			  GValue *value, GParamSpec *pspec)
{
	NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (object);
	GPtrArray *devices;

	switch (prop_id) {
	case PROP_CONNECTION:
		g_value_set_boxed (value, nm_connection_get_path (priv->connection));
		break;
	case PROP_UUID:
		g_value_set_string (value, nm_connection_get_uuid (priv->connection));
		break;
	case PROP_SPECIFIC_OBJECT:
		g_value_set_boxed (value, priv->specific_object ? priv->specific_object : "/");
		break;
	case PROP_DEVICES:
		devices = g_ptr_array_sized_new (1);
		g_ptr_array_add (devices, g_strdup (priv->device_path));
		g_value_take_boxed (value, devices);
		break;
	case PROP_STATE:
		g_value_set_uint (value, priv->state);
		break;
	case PROP_DEFAULT:
		g_value_set_boolean (value, priv->is_default);
		break;
	case PROP_DEFAULT6:
		g_value_set_boolean (value, priv->is_default6);
		break;
	case PROP_VPN:
		g_value_set_boolean (value, priv->vpn);
		break;
	case PROP_MASTER:
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}
void
nm_settings_service_export_connection (NMSettingsService *self,
                                       NMSettingsConnectionInterface *connection)
{
	NMSettingsServicePrivate *priv = NM_SETTINGS_SERVICE_GET_PRIVATE (self);
	static guint32 ec_counter = 0;
	char *path;

	g_return_if_fail (connection != NULL);
	g_return_if_fail (NM_IS_SETTINGS_CONNECTION_INTERFACE (connection));
	g_return_if_fail (priv->bus != NULL);

	/* Don't allow exporting twice */
	g_return_if_fail (nm_connection_get_path (NM_CONNECTION (connection)) == NULL);

	path = g_strdup_printf ("%s/%u", NM_DBUS_PATH_SETTINGS, ec_counter++);
	nm_connection_set_path (NM_CONNECTION (connection), path);
	nm_connection_set_scope (NM_CONNECTION (connection), priv->scope);

	dbus_g_connection_register_g_object (priv->bus, path, G_OBJECT (connection));
	g_free (path);
}
예제 #21
0
static void
connection_removed_cb (NMRemoteConnection *remote, gpointer user_data)
{
	NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
	NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
	AddConnectionInfo *addinfo;
	GError *add_error;
	const char *path;

	/* Might have been removed while it was waiting to be initialized */
	addinfo = add_connection_info_find (self, remote);
	if (addinfo) {
		add_error = g_error_new_literal (NM_REMOTE_SETTINGS_ERROR,
		                                 NM_REMOTE_SETTINGS_ERROR_CONNECTION_REMOVED,
		                                 "Connection removed before it was initialized");
		add_connection_info_complete (self, addinfo, add_error);
		g_error_free (add_error);
	}

	path = nm_connection_get_path (NM_CONNECTION (remote));
	g_hash_table_remove (priv->connections, path);
	g_hash_table_remove (priv->pending, path);
}
예제 #22
0
static gboolean
_dispatcher_call (DispatcherAction action,
                  gboolean blocking,
                  NMSettingsConnection *settings_connection,
                  NMConnection *applied_connection,
                  NMDevice *device,
                  NMConnectivityState connectivity_state,
                  const char *vpn_iface,
                  NMProxyConfig *vpn_proxy_config,
                  NMIP4Config *vpn_ip4_config,
                  NMIP6Config *vpn_ip6_config,
                  DispatcherFunc callback,
                  gpointer user_data,
                  guint *out_call_id)
{
	GVariant *connection_dict;
	GVariantBuilder connection_props;
	GVariantBuilder device_props;
	GVariantBuilder device_proxy_props;
	GVariantBuilder device_ip4_props;
	GVariantBuilder device_ip6_props;
	GVariant *device_dhcp4_props = NULL;
	GVariant *device_dhcp6_props = NULL;
	GVariantBuilder vpn_proxy_props;
	GVariantBuilder vpn_ip4_props;
	GVariantBuilder vpn_ip6_props;
	DispatchInfo *info = NULL;
	gboolean success = FALSE;
	GError *error = NULL;
	static guint request_counter = 0;
	guint reqid = ++request_counter;

	if (!dispatcher_proxy)
		return FALSE;

	/* Wrapping protection */
	if (G_UNLIKELY (!reqid))
		reqid = ++request_counter;

	g_assert (!blocking || (!callback && !user_data));

	_ensure_requests ();

	/* All actions except 'hostname' and 'connectivity-change' require a device */
	if (   action == DISPATCHER_ACTION_HOSTNAME
	    || action == DISPATCHER_ACTION_CONNECTIVITY_CHANGE) {
		_LOGD ("(%u) dispatching action '%s'%s",
		       reqid, action_to_string (action),
		       blocking
		           ? " (blocking)"
		           : (callback ? " (with callback)" : ""));
	} else {
		g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);

		_LOGD ("(%u) (%s) dispatching action '%s'%s",
		       reqid,
		       vpn_iface ? vpn_iface : nm_device_get_iface (device),
		       action_to_string (action),
		       blocking
		           ? " (blocking)"
		           : (callback ? " (with callback)" : ""));
	}

	if (!_get_monitor_by_action(action)->has_scripts) {
		if (blocking == FALSE && (out_call_id || callback)) {
			info = g_malloc0 (sizeof (*info));
			info->action = action;
			info->request_id = reqid;
			info->callback = callback;
			info->user_data = user_data;
			info->idle_id = g_idle_add (dispatcher_idle_cb, info);
			_LOGD ("(%u) simulate request; no scripts in %s",  reqid, _get_monitor_by_action(action)->dir);
		} else
			_LOGD ("(%u) ignoring request; no scripts in %s", reqid, _get_monitor_by_action(action)->dir);
		success = TRUE;
		goto done;
	}

	if (applied_connection)
		connection_dict = nm_connection_to_dbus (applied_connection, NM_CONNECTION_SERIALIZE_NO_SECRETS);
	else
		connection_dict = g_variant_new_array (G_VARIANT_TYPE ("{sa{sv}}"), NULL, 0);

	g_variant_builder_init (&connection_props, G_VARIANT_TYPE_VARDICT);
	if (settings_connection) {
		const char *connection_path;
		const char *filename;

		connection_path = nm_connection_get_path (NM_CONNECTION (settings_connection));
		if (connection_path) {
			g_variant_builder_add (&connection_props, "{sv}",
			                       NMD_CONNECTION_PROPS_PATH,
			                       g_variant_new_object_path (connection_path));
		}
		filename = nm_settings_connection_get_filename (settings_connection);
		if (filename) {
			g_variant_builder_add (&connection_props, "{sv}",
			                       NMD_CONNECTION_PROPS_FILENAME,
			                       g_variant_new_string (filename));
		}
		if (nm_settings_connection_get_nm_generated_assumed (settings_connection)) {
			g_variant_builder_add (&connection_props, "{sv}",
			                       NMD_CONNECTION_PROPS_EXTERNAL,
			                       g_variant_new_boolean (TRUE));
		}
	}

	g_variant_builder_init (&device_props, G_VARIANT_TYPE_VARDICT);
	g_variant_builder_init (&device_proxy_props, G_VARIANT_TYPE_VARDICT);
	g_variant_builder_init (&device_ip4_props, G_VARIANT_TYPE_VARDICT);
	g_variant_builder_init (&device_ip6_props, G_VARIANT_TYPE_VARDICT);
	g_variant_builder_init (&vpn_proxy_props, G_VARIANT_TYPE_VARDICT);
	g_variant_builder_init (&vpn_ip4_props, G_VARIANT_TYPE_VARDICT);
	g_variant_builder_init (&vpn_ip6_props, G_VARIANT_TYPE_VARDICT);

	/* hostname and connectivity-change actions don't send device data */
	if (   action != DISPATCHER_ACTION_HOSTNAME
	    && action != DISPATCHER_ACTION_CONNECTIVITY_CHANGE) {
		fill_device_props (device,
		                   &device_props,
		                   &device_proxy_props,
		                   &device_ip4_props,
		                   &device_ip6_props,
		                   &device_dhcp4_props,
		                   &device_dhcp6_props);
		if (vpn_ip4_config || vpn_ip6_config) {
			fill_vpn_props (vpn_proxy_config,
			                vpn_ip4_config,
			                vpn_ip6_config,
			                &vpn_proxy_props,
			                &vpn_ip4_props,
			                &vpn_ip6_props);
		}
	}

	if (!device_dhcp4_props)
		device_dhcp4_props = g_variant_ref_sink (g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0));
	if (!device_dhcp6_props)
		device_dhcp6_props = g_variant_ref_sink (g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0));

	/* Send the action to the dispatcher */
	if (blocking) {
		GVariant *ret;
		GVariantIter *results;

		ret = _nm_dbus_proxy_call_sync (dispatcher_proxy, "Action",
		                                g_variant_new ("(s@a{sa{sv}}a{sv}a{sv}a{sv}a{sv}a{sv}@a{sv}@a{sv}ssa{sv}a{sv}a{sv}b)",
		                                               action_to_string (action),
		                                               connection_dict,
		                                               &connection_props,
		                                               &device_props,
		                                               &device_proxy_props,
		                                               &device_ip4_props,
		                                               &device_ip6_props,
		                                               device_dhcp4_props,
		                                               device_dhcp6_props,
		                                               nm_connectivity_state_to_string (connectivity_state),
		                                               vpn_iface ? vpn_iface : "",
		                                               &vpn_proxy_props,
		                                               &vpn_ip4_props,
		                                               &vpn_ip6_props,
		                                               nm_logging_enabled (LOGL_DEBUG, LOGD_DISPATCH)),
		                                G_VARIANT_TYPE ("(a(sus))"),
		                                G_DBUS_CALL_FLAGS_NONE, CALL_TIMEOUT,
		                                NULL, &error);
		if (ret) {
			g_variant_get (ret, "(a(sus))", &results);
			dispatcher_results_process (reqid, action, results);
			g_variant_iter_free (results);
			g_variant_unref (ret);
			success = TRUE;
		} else {
			g_dbus_error_strip_remote_error (error);
			_LOGW ("(%u) failed: %s", reqid, error->message);
			g_clear_error (&error);
			success = FALSE;
		}
	} else {
		info = g_malloc0 (sizeof (*info));
		info->action = action;
		info->request_id = reqid;
		info->callback = callback;
		info->user_data = user_data;
		g_dbus_proxy_call (dispatcher_proxy, "Action",
		                   g_variant_new ("(s@a{sa{sv}}a{sv}a{sv}a{sv}a{sv}a{sv}@a{sv}@a{sv}ssa{sv}a{sv}a{sv}b)",
		                                  action_to_string (action),
		                                  connection_dict,
		                                  &connection_props,
		                                  &device_props,
		                                  &device_proxy_props,
		                                  &device_ip4_props,
		                                  &device_ip6_props,
		                                  device_dhcp4_props,
		                                  device_dhcp6_props,
		                                  nm_connectivity_state_to_string (connectivity_state),
		                                  vpn_iface ? vpn_iface : "",
		                                  &vpn_proxy_props,
		                                  &vpn_ip4_props,
		                                  &vpn_ip6_props,
		                                  nm_logging_enabled (LOGL_DEBUG, LOGD_DISPATCH)),
		                   G_DBUS_CALL_FLAGS_NONE, CALL_TIMEOUT,
		                   NULL, dispatcher_done_cb, info);
		success = TRUE;
	}

	g_variant_unref (device_dhcp4_props);
	g_variant_unref (device_dhcp6_props);

done:
	if (success && info) {
		/* Track the request in case of cancelation */
		g_hash_table_insert (requests, GUINT_TO_POINTER (info->request_id), info);
		if (out_call_id)
			*out_call_id = info->request_id;
	} else if (out_call_id)
		*out_call_id = 0;

	return success;
}
static gboolean
impl_ifcfgrh_get_ifcfg_details (SCPluginIfcfg *plugin,
                                const char *in_ifcfg,
                                const char **out_uuid,
                                const char **out_path,
                                GError **error)
{
	NMIfcfgConnection *connection;
	NMSettingConnection *s_con;
	const char *uuid;
	const char *path;

	if (!g_path_is_absolute (in_ifcfg)) {
		g_set_error (error,
		             NM_SETTINGS_ERROR,
		             NM_SETTINGS_ERROR_INVALID_CONNECTION,
		             "ifcfg path '%s' is not absolute", in_ifcfg);
		return FALSE;
	}

	connection = find_by_path (plugin, in_ifcfg);
	if (   !connection
	    || nm_ifcfg_connection_get_unmanaged_spec (connection)
	    || nm_ifcfg_connection_get_unrecognized_spec (connection)) {
		g_set_error (error,
		             NM_SETTINGS_ERROR,
		             NM_SETTINGS_ERROR_INVALID_CONNECTION,
		             "ifcfg file '%s' unknown", in_ifcfg);
		return FALSE;
	}

	s_con = nm_connection_get_setting_connection (NM_CONNECTION (connection));
	if (!s_con) {
		g_set_error (error,
		             NM_SETTINGS_ERROR,
		             NM_SETTINGS_ERROR_FAILED,
		             "unable to retrieve the connection setting");
		return FALSE;
	}

	uuid = nm_setting_connection_get_uuid (s_con);
	if (!uuid) {
		g_set_error (error,
		             NM_SETTINGS_ERROR,
		             NM_SETTINGS_ERROR_FAILED,
		             "unable to get the UUID");
		return FALSE;
	}
	
	path = nm_connection_get_path (NM_CONNECTION (connection));
	if (!path) {
		g_set_error (error,
		             NM_SETTINGS_ERROR,
		             NM_SETTINGS_ERROR_FAILED,
		             "unable to get the connection D-Bus path");
		return FALSE;
	}

	*out_uuid = g_strdup (uuid);
	*out_path = g_strdup (path);

	return TRUE;
}
예제 #24
0
static void
connection_init_result_cb (NMRemoteConnection *remote,
                           GParamSpec *pspec,
                           gpointer user_data)
{
	NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
	NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
	guint32 init_result = NM_REMOTE_CONNECTION_INIT_RESULT_UNKNOWN;
	AddConnectionInfo *addinfo;
	const char *path;
	GError *add_error = NULL;
	gboolean remove_from_pending = TRUE;

	/* Disconnect from the init-result signal just to be safe */
	g_signal_handlers_disconnect_matched (remote,
	                                      G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
	                                      0,
	                                      0,
	                                      NULL,
	                                      G_CALLBACK (connection_init_result_cb),
	                                      self);

	path = nm_connection_get_path (NM_CONNECTION (remote));

	g_object_get (G_OBJECT (remote),
	              NM_REMOTE_CONNECTION_INIT_RESULT, &init_result,
	              NULL);

	addinfo = add_connection_info_find (self, remote);

	switch (init_result) {
	case NM_REMOTE_CONNECTION_INIT_RESULT_SUCCESS:
		/* ref it when adding to ->connections, since removing it from ->pending
		 * will unref it.
		 */
		g_hash_table_insert (priv->connections, g_strdup (path), g_object_ref (remote));

		/* If there's a pending AddConnection request, complete that here before
		 * signaling new-connection.
		 */
		if (addinfo)
			add_connection_info_complete (self, addinfo, NULL);

		/* Finally, let users know of the new connection now that it has all
		 * its settings and is valid.
		 */
		g_signal_emit (self, signals[NEW_CONNECTION], 0, remote);
		break;
	case NM_REMOTE_CONNECTION_INIT_RESULT_INVISIBLE:
		remove_from_pending = FALSE;
		/* fall through */
	case NM_REMOTE_CONNECTION_INIT_RESULT_ERROR:
		/* Complete pending AddConnection callbacks */
		if (addinfo) {
			add_error = g_error_new_literal (NM_REMOTE_SETTINGS_ERROR,
			                                 NM_REMOTE_SETTINGS_ERROR_CONNECTION_UNAVAILABLE,
			                                 "Connection not visible or not available");
			add_connection_info_complete (self, addinfo, add_error);
			g_error_free (add_error);
		}
		break;
	default:
		break;
	}

	if (remove_from_pending)
		g_hash_table_remove (priv->pending, path);

	/* Let listeners know that all connections have been found */
	priv->init_left--;
	if (priv->init_left == 0)
		g_signal_emit (self, signals[CONNECTIONS_READ], 0);
}
static void
test_make_invisible (void)
{
	time_t start, now;
	const GPtrArray *conns;
	int i;
	GDBusProxy *proxy;
	gboolean visible_changed = FALSE, connection_removed = FALSE;
	gboolean has_settings = FALSE;
	char *path;

	g_assert (remote != NULL);

	/* Listen for the remove event when the connection becomes invisible */
	g_signal_connect (remote, "notify::" NM_REMOTE_CONNECTION_VISIBLE, G_CALLBACK (visible_changed_cb), &visible_changed);
	g_signal_connect (client, "connection-removed", G_CALLBACK (connection_removed_cb), &connection_removed);

	path = g_strdup (nm_connection_get_path (NM_CONNECTION (remote)));
	proxy = g_dbus_proxy_new_sync (bus,
	                               G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
	                               NULL,
	                               NM_DBUS_SERVICE,
	                               path,
	                               NM_DBUS_INTERFACE_SETTINGS_CONNECTION,
	                               NULL,
	                               NULL);
	g_assert (proxy != NULL);

	/* Bypass the NMClient object so we can test it independently */
	g_dbus_proxy_call (proxy,
	                   "SetVisible",
	                   g_variant_new ("(b)", FALSE),
	                   G_DBUS_CALL_FLAGS_NONE, -1,
	                   NULL,
	                   set_visible_cb, NULL);

	/* Wait for the connection to be removed */
	start = time (NULL);
	do {
		now = time (NULL);
		g_main_context_iteration (NULL, FALSE);
	} while ((!visible_changed || !connection_removed) && (now - start < 5));
	g_assert (visible_changed == TRUE);
	g_assert (connection_removed == TRUE);

	g_signal_handlers_disconnect_by_func (remote, G_CALLBACK (visible_changed_cb), &visible_changed);
	g_signal_handlers_disconnect_by_func (client, G_CALLBACK (connection_removed_cb), &connection_removed);

	/* Ensure NMClient no longer has the connection */
	conns = nm_client_get_connections (client);
	for (i = 0; i < conns->len; i++) {
		NMConnection *candidate = NM_CONNECTION (conns->pdata[i]);

		g_assert ((gpointer) remote != (gpointer) candidate);
		g_assert (strcmp (path, nm_connection_get_path (candidate)) != 0);
	}

	/* And ensure the invisible connection no longer has any settings */
	g_assert (remote);
	nm_connection_for_each_setting_value (NM_CONNECTION (remote),
	                                      invis_has_settings_cb,
	                                      &has_settings);
	g_assert (has_settings == FALSE);

	g_free (path);
	g_object_unref (proxy);
}
예제 #26
0
static void
get_property (GObject *object, guint prop_id,
              GValue *value, GParamSpec *pspec)
{
	NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (object);
	GPtrArray *devices;
	NMDevice *master_device = NULL;

	switch (prop_id) {
	case PROP_CONNECTION:
		g_value_set_string (value, nm_connection_get_path (NM_CONNECTION (priv->settings_connection)));
		break;
	case PROP_ID:
		g_value_set_string (value, nm_connection_get_id (NM_CONNECTION (priv->settings_connection)));
		break;
	case PROP_UUID:
		g_value_set_string (value, nm_connection_get_uuid (NM_CONNECTION (priv->settings_connection)));
		break;
	case PROP_TYPE:
		g_value_set_string (value, nm_connection_get_connection_type (NM_CONNECTION (priv->settings_connection)));
		break;
	case PROP_SPECIFIC_OBJECT:
		g_value_set_string (value, priv->specific_object ? priv->specific_object : "/");
		break;
	case PROP_DEVICES:
		devices = g_ptr_array_sized_new (2);
		if (priv->device && priv->state < NM_ACTIVE_CONNECTION_STATE_DEACTIVATED)
			g_ptr_array_add (devices, g_strdup (nm_exported_object_get_path (NM_EXPORTED_OBJECT (priv->device))));
		g_ptr_array_add (devices, NULL);
		g_value_take_boxed (value, (char **) g_ptr_array_free (devices, FALSE));
		break;
	case PROP_STATE:
		if (priv->state_set)
			g_value_set_uint (value, priv->state);
		else {
			/* When the AC has just been created, its externally-visible state should
			 * be "ACTIVATING", even though internally it is "UNKNOWN".
			 */
			g_value_set_uint (value, NM_ACTIVE_CONNECTION_STATE_ACTIVATING);
		}
		break;
	case PROP_DEFAULT:
		g_value_set_boolean (value, priv->is_default);
		break;
	case PROP_IP4_CONFIG:
		/* The IP and DHCP config properties may be overridden by a subclass */
		g_value_set_string (value, "/");
		break;
	case PROP_DHCP4_CONFIG:
		g_value_set_string (value, "/");
		break;
	case PROP_DEFAULT6:
		g_value_set_boolean (value, priv->is_default6);
		break;
	case PROP_IP6_CONFIG:
		g_value_set_string (value, "/");
		break;
	case PROP_DHCP6_CONFIG:
		g_value_set_string (value, "/");
		break;
	case PROP_VPN:
		g_value_set_boolean (value, priv->vpn);
		break;
	case PROP_MASTER:
		if (priv->master)
			master_device = nm_active_connection_get_device (priv->master);
		nm_utils_g_value_set_object_path (value, master_device);
		break;
	case PROP_INT_SUBJECT:
		g_value_set_object (value, priv->subject);
		break;
	case PROP_INT_MASTER_READY:
		g_value_set_boolean (value, priv->master_ready);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}
static void
add_row (NetDeviceEthernet *device, NMConnection *connection)
{
        GtkWidget *row;
        GtkWidget *widget;
        GtkWidget *box;
        GtkWidget *details;
        NMDevice *nmdev;
        NMActiveConnection *aconn;
        gboolean active;
        GtkWidget *image;

        active = FALSE;

        nmdev = net_device_get_nm_device (NET_DEVICE (device));
        aconn = nm_device_get_active_connection (nmdev);
        if (aconn) {
                const gchar *path1, *path2;
                path1 = nm_active_connection_get_connection (aconn);
                path2 = nm_connection_get_path (connection);
                active = g_strcmp0 (path1, path2) == 0;
        }

        row = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
        box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
        gtk_box_pack_start (GTK_BOX (row), box, FALSE, TRUE, 0);
        widget = gtk_label_new (nm_connection_get_id (connection));
        gtk_widget_set_margin_left (widget, 12);
        gtk_widget_set_margin_right (widget, 12);
        gtk_widget_set_margin_top (widget, 12);
        gtk_widget_set_margin_bottom (widget, 12);
        gtk_box_pack_start (GTK_BOX (box), widget, FALSE, TRUE, 0);

        if (active) {
                widget = gtk_image_new_from_icon_name ("object-select-symbolic", GTK_ICON_SIZE_MENU);
                gtk_widget_set_halign (widget, GTK_ALIGN_CENTER);
                gtk_widget_set_valign (widget, GTK_ALIGN_CENTER);
                gtk_box_pack_start (GTK_BOX (box), widget, FALSE, TRUE, 0);

                details = gtk_grid_new ();
                gtk_grid_set_row_spacing (GTK_GRID (details), 10);
                gtk_grid_set_column_spacing (GTK_GRID (details), 10);

                gtk_box_pack_start (GTK_BOX (row), details, FALSE, TRUE, 0);

                add_details (details, nmdev, connection);
        }

        /* filler */
        widget = gtk_label_new ("");
        gtk_widget_set_hexpand (widget, TRUE);
        gtk_box_pack_start (GTK_BOX (box), widget, TRUE, TRUE, 0);

        image = gtk_image_new_from_icon_name ("emblem-system-symbolic", GTK_ICON_SIZE_MENU);
        gtk_widget_show (image);
        widget = gtk_button_new ();
        gtk_style_context_add_class (gtk_widget_get_style_context (widget), "image-button");
        gtk_widget_set_margin_left (widget, 12);
        gtk_widget_set_margin_right (widget, 12);
        gtk_widget_set_margin_top (widget, 12);
        gtk_widget_set_margin_bottom (widget, 12);
        gtk_widget_show (widget);
        gtk_container_add (GTK_CONTAINER (widget), image);
        gtk_widget_set_halign (widget, GTK_ALIGN_CENTER);
        gtk_widget_set_valign (widget, GTK_ALIGN_CENTER);
        atk_object_set_name (gtk_widget_get_accessible (widget), _("Options…"));
        gtk_box_pack_start (GTK_BOX (box), widget, FALSE, TRUE, 0);
        g_object_set_data (G_OBJECT (row), "edit", widget);
        g_object_set_data (G_OBJECT (widget), "row", row);
        g_signal_connect (widget, "clicked",
                          G_CALLBACK (show_details_for_row), device);

        gtk_widget_show_all (row);

        g_object_set_data (G_OBJECT (row), "connection", connection);

        gtk_container_add (GTK_CONTAINER (device->list), row);
}
static void
connect_details_page (CEPageDetails *page)
{
        guint speed;
        guint strength;
        NMDeviceState state;
        NMAccessPoint *active_ap;
        const gchar *str;
        gboolean device_is_active;

        if (NM_IS_DEVICE_WIFI (page->device))
                active_ap = nm_device_wifi_get_active_access_point (NM_DEVICE_WIFI (page->device));
        else
                active_ap = NULL;

        state = page->device ? nm_device_get_state (page->device) : NM_DEVICE_STATE_DISCONNECTED;

        device_is_active = FALSE;
        speed = 0;
        if (active_ap && page->ap == active_ap && state != NM_DEVICE_STATE_UNAVAILABLE) {
                device_is_active = TRUE;
                if (NM_IS_DEVICE_WIFI (page->device))
                        speed = nm_device_wifi_get_bitrate (NM_DEVICE_WIFI (page->device)) / 1000;
        } else if (page->device) {
                NMActiveConnection *ac;
                const gchar *p1, *p2;

                ac = nm_device_get_active_connection (page->device);
                p1 = ac ? nm_active_connection_get_connection (ac) : NULL;
                p2 = nm_connection_get_path (CE_PAGE (page)->connection);
                if (g_strcmp0 (p1, p2) == 0) {
                        device_is_active = TRUE;
                        if (NM_IS_DEVICE_WIFI (page->device))
                                speed = nm_device_wifi_get_bitrate (NM_DEVICE_WIFI (page->device)) / 1000;
                        else if (NM_IS_DEVICE_ETHERNET (page->device))
                                speed = nm_device_ethernet_get_speed (NM_DEVICE_ETHERNET (page->device));
                }
        }
        if (speed > 0)
                str = g_strdup_printf (_("%d Mb/s"), speed);
        else
                str = NULL;
        panel_set_device_widget_details (CE_PAGE (page)->builder, "speed", str);
        g_clear_pointer (&str, g_free);

        if (NM_IS_DEVICE_WIFI (page->device))
                str = nm_device_wifi_get_hw_address (NM_DEVICE_WIFI (page->device));
        else if (NM_IS_DEVICE_ETHERNET (page->device))
                str = nm_device_ethernet_get_hw_address (NM_DEVICE_ETHERNET (page->device));

        panel_set_device_widget_details (CE_PAGE (page)->builder, "mac", str);

        str = NULL;
        if (device_is_active && active_ap)
                str = get_ap_security_string (active_ap);
        panel_set_device_widget_details (CE_PAGE (page)->builder, "security", str);
        g_clear_pointer (&str, g_free);

        strength = 0;
        if (page->ap != NULL)
                strength = nm_access_point_get_strength (page->ap);

        if (strength <= 0)
                str = NULL;
        else if (strength < 20)
                str = C_("Signal strength", "None");
        else if (strength < 40)
                str = C_("Signal strength", "Weak");
        else if (strength < 50)
                str = C_("Signal strength", "Ok");
        else if (strength < 80)
                str = C_("Signal strength", "Good");
        else
                str = C_("Signal strength", "Excellent");
        panel_set_device_widget_details (CE_PAGE (page)->builder, "strength", str);

        /* set IP entries */
        if (device_is_active)
                panel_set_device_widgets (CE_PAGE (page)->builder, page->device);
        else
                panel_unset_device_widgets (CE_PAGE (page)->builder);

        if (!device_is_active && CE_PAGE (page)->connection)
                update_last_used (page, CE_PAGE (page)->connection);
        else
                panel_set_device_widget_details (CE_PAGE (page)->builder, "last_used", NULL);

}