summary refs log tree commit diff
path: root/clients/tui/nm-editor-utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'clients/tui/nm-editor-utils.c')
-rw-r--r--clients/tui/nm-editor-utils.c414
1 files changed, 414 insertions, 0 deletions
diff --git a/clients/tui/nm-editor-utils.c b/clients/tui/nm-editor-utils.c
new file mode 100644
index 00000000..f936c959
--- /dev/null
+++ b/clients/tui/nm-editor-utils.c
@@ -0,0 +1,414 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright 2012, 2013 Red Hat, Inc.
+ */
+
+/**
+ * SECTION:nm-editor-utils
+ * @short_description: Miscellaneous connection editor utilities
+ *
+ * nm-editor-utils contains helper functions for connection editors.
+ * The goal is that this should eventually be shared between nmtui,
+ * nm-connection-editor, and gnome-control-center.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <NetworkManager.h>
+
+#include "nm-editor-utils.h"
+#if 0
+#include "vpn-helpers.h"
+
+static GSList *vpn_plugins;
+
+static gint
+sort_vpn_plugins (gconstpointer a, gconstpointer b)
+{
+	NMVpnPluginUiInterface *aa = NM_VPN_PLUGIN_UI_INTERFACE (a);
+	NMVpnPluginUiInterface *bb = NM_VPN_PLUGIN_UI_INTERFACE (b);
+	char *aa_desc = NULL, *bb_desc = NULL;
+	int ret;
+
+	g_object_get (aa, NM_VPN_PLUGIN_UI_INTERFACE_NAME, &aa_desc, NULL);
+	g_object_get (bb, NM_VPN_PLUGIN_UI_INTERFACE_NAME, &bb_desc, NULL);
+
+	ret = g_strcmp0 (aa_desc, bb_desc);
+
+	g_free (aa_desc);
+	g_free (bb_desc);
+
+	return ret;
+}
+#endif
+
+static void
+wifi_connection_setup_func (NMConnection        *connection,
+                            NMSettingConnection *s_con,
+                            NMSetting           *s_hw)
+{
+	g_object_set (G_OBJECT (s_hw),
+	              NM_SETTING_WIRELESS_MODE, NM_SETTING_WIRELESS_MODE_INFRA,
+	              NULL);
+}
+
+static void
+bond_connection_setup_func (NMConnection        *connection,
+                            NMSettingConnection *s_con,
+                            NMSetting           *s_hw)
+{
+	NMSettingBond *s_bond = NM_SETTING_BOND (s_hw);
+	const char **options, *def, *cur;
+	int i;
+
+	options = nm_setting_bond_get_valid_options (s_bond);
+	for (i = 0; options[i]; i++) {
+		def = nm_setting_bond_get_option_default (s_bond, options[i]);
+		cur = nm_setting_bond_get_option_by_name (s_bond, options[i]);
+		if (g_strcmp0 (def, cur) != 0)
+			nm_setting_bond_add_option (s_bond, options[i], def);
+	}
+}
+
+typedef void (*NMEditorNewConnectionSetupFunc) (NMConnection        *connection,
+                                                NMSettingConnection *s_con,
+                                                NMSetting           *s_hw);
+
+typedef struct {
+	NMEditorConnectionTypeData data;
+
+	const char *id_format;
+	NMEditorNewConnectionSetupFunc connection_setup_func;
+	gboolean no_autoconnect;
+} NMEditorConnectionTypeDataReal;
+
+static gint
+sort_types (gconstpointer a, gconstpointer b)
+{
+	NMEditorConnectionTypeData *typea = *(NMEditorConnectionTypeData **)a;
+	NMEditorConnectionTypeData *typeb = *(NMEditorConnectionTypeData **)b;
+
+	if (typea->virtual && !typeb->virtual)
+		return 1;
+	else if (typeb->virtual && !typea->virtual)
+		return -1;
+
+	if (typea->setting_type == NM_TYPE_SETTING_VPN &&
+	    typeb->setting_type != NM_TYPE_SETTING_VPN)
+		return 1;
+	else if (typeb->setting_type == NM_TYPE_SETTING_VPN &&
+	         typea->setting_type != NM_TYPE_SETTING_VPN)
+		return -1;
+
+	return g_utf8_collate (typea->name, typeb->name);
+}
+
+/**
+ * nm_editor_utils_get_connection_type_list:
+ *
+ * Gets an array of information about supported connection types. The
+ * array is sorted in a standard presentation order (hardware types
+ * first, alphabetized, then virtual types, alphabetized, then VPN
+ * types, alphabetized).
+ *
+ * Returns: the array of connection type information
+ */
+NMEditorConnectionTypeData **
+nm_editor_utils_get_connection_type_list (void)
+{
+	GPtrArray *array;
+	NMEditorConnectionTypeDataReal *item;
+	static NMEditorConnectionTypeData **list;
+#if 0
+	GHashTable *vpn_plugins_hash;
+	gboolean have_vpn_plugins;
+#endif
+
+	if (list)
+		return list;
+
+	array = g_ptr_array_new ();
+
+	item = g_new0 (NMEditorConnectionTypeDataReal, 1);
+	item->data.name = _("Ethernet");
+	item->data.setting_type = NM_TYPE_SETTING_WIRED;
+	item->data.device_type = NM_TYPE_DEVICE_ETHERNET;
+	item->data.virtual = FALSE;
+	item->id_format = _("Ethernet connection %d");
+	g_ptr_array_add (array, item);
+
+	item = g_new0 (NMEditorConnectionTypeDataReal, 1);
+	item->data.name = _("Wi-Fi");
+	item->data.setting_type = NM_TYPE_SETTING_WIRELESS;
+	item->data.device_type = NM_TYPE_DEVICE_WIFI;
+	item->data.virtual = FALSE;
+	item->id_format = _("Wi-Fi connection %d");
+	item->connection_setup_func = wifi_connection_setup_func;
+	g_ptr_array_add (array, item);
+
+	item = g_new0 (NMEditorConnectionTypeDataReal, 1);
+	item->data.name = _("InfiniBand");
+	item->data.setting_type = NM_TYPE_SETTING_INFINIBAND;
+	item->data.device_type = NM_TYPE_DEVICE_INFINIBAND;
+	item->data.virtual = FALSE;
+	item->id_format = _("InfiniBand connection %d");
+	g_ptr_array_add (array, item);
+
+#if 0
+	item = g_new0 (NMEditorConnectionTypeDataReal, 1);
+	item->data.name = _("Mobile Broadband");
+	item->data.setting_type = NM_TYPE_SETTING_GSM;
+	item->data.virtual = FALSE;
+	item->id_format = _("Mobile broadband connection %d");
+	item->no_autoconnect = TRUE;
+	g_ptr_array_add (array, item);
+#endif
+
+	item = g_new0 (NMEditorConnectionTypeDataReal, 1);
+	item->data.name = _("DSL");
+	item->data.setting_type = NM_TYPE_SETTING_PPPOE;
+	item->data.device_type = NM_TYPE_DEVICE_ETHERNET;
+	item->data.virtual = FALSE;
+	item->id_format = _("DSL connection %d");
+	item->no_autoconnect = TRUE;
+	g_ptr_array_add (array, item);
+
+	item = g_new0 (NMEditorConnectionTypeDataReal, 1);
+	item->data.name = _("Bond");
+	item->data.setting_type = NM_TYPE_SETTING_BOND;
+	item->data.device_type = NM_TYPE_DEVICE_BOND;
+	item->data.virtual = TRUE;
+	item->id_format = _("Bond connection %d");
+	item->connection_setup_func = bond_connection_setup_func;
+	g_ptr_array_add (array, item);
+
+	item = g_new0 (NMEditorConnectionTypeDataReal, 1);
+	item->data.name = _("Bridge");
+	item->data.setting_type = NM_TYPE_SETTING_BRIDGE;
+	item->data.slave_setting_type = NM_TYPE_SETTING_BRIDGE_PORT;
+	item->data.device_type = NM_TYPE_DEVICE_BRIDGE;
+	item->data.virtual = TRUE;
+	item->id_format = _("Bridge connection %d");
+	g_ptr_array_add (array, item);
+
+	item = g_new0 (NMEditorConnectionTypeDataReal, 1);
+	item->data.name = _("Team");
+	item->data.setting_type = NM_TYPE_SETTING_TEAM;
+	item->data.slave_setting_type = NM_TYPE_SETTING_TEAM_PORT;
+	item->data.device_type = NM_TYPE_DEVICE_TEAM;
+	item->data.virtual = TRUE;
+	item->id_format = _("Team connection %d");
+	g_ptr_array_add (array, item);
+
+	item = g_new0 (NMEditorConnectionTypeDataReal, 1);
+	item->data.name = _("VLAN");
+	item->data.setting_type = NM_TYPE_SETTING_VLAN;
+	item->data.device_type = NM_TYPE_DEVICE_VLAN;
+	item->data.virtual = TRUE;
+	item->id_format = _("VLAN connection %d");
+	g_ptr_array_add (array, item);
+
+#if 0
+	/* Add "VPN" only if there are plugins */
+	vpn_plugins_hash = vpn_get_plugins (NULL);
+	have_vpn_plugins  = vpn_plugins_hash && g_hash_table_size (vpn_plugins_hash);
+	if (have_vpn_plugins) {
+		GHashTableIter iter;
+		gpointer name, plugin;
+
+		item = g_new0 (NMEditorConnectionTypeDataReal, 1);
+		item->data.name = _("VPN");
+		item->data.setting_type = NM_TYPE_SETTING_VPN;
+		item->data.virtual = TRUE;
+		item->id_format = _("VPN connection %d");
+		item->no_autoconnect = TRUE;
+		g_ptr_array_add (array, item);
+
+		vpn_plugins = NULL;
+		g_hash_table_iter_init (&iter, vpn_plugins_hash);
+		while (g_hash_table_iter_next (&iter, &name, &plugin))
+			vpn_plugins = g_slist_prepend (vpn_plugins, plugin);
+		vpn_plugins = g_slist_sort (vpn_plugins, sort_vpn_plugins);
+	}
+#endif
+
+	g_ptr_array_sort (array, sort_types);
+	g_ptr_array_add (array, NULL);
+
+	list = (NMEditorConnectionTypeData **)g_ptr_array_free (array, FALSE);
+	return list;
+}
+
+static char *
+get_available_connection_name (const char *format,
+                               NMClient   *client)
+{
+	const GPtrArray *conns;
+	GSList *names = NULL, *iter;
+	char *cname = NULL;
+	int i = 0;
+
+	conns = nm_client_get_connections (client);
+	for (i = 0; i < conns->len; i++) {
+		const char *id;
+
+		id = nm_connection_get_id (NM_CONNECTION (conns->pdata[i]));
+		g_assert (id);
+		names = g_slist_append (names, (gpointer) id);
+	}
+
+	/* Find the next available unique connection name */
+	for (i = 1; !cname && i < 10000; i++) {
+		char *temp;
+		gboolean found = FALSE;
+
+		temp = g_strdup_printf (format, i);
+		for (iter = names; iter; iter = g_slist_next (iter)) {
+			if (!strcmp (iter->data, temp)) {
+				found = TRUE;
+				break;
+			}
+		}
+		if (!found)
+			cname = temp;
+		else
+			g_free (temp);
+	}
+
+	g_slist_free (names);
+	return cname;
+}
+
+/**
+ * nm_editor_utils_create_connection:
+ * @type: the type of the connection's primary #NMSetting
+ * @master: (allow-none): the connection's master, if any
+ * @client: an #NMClient
+ *
+ * Creates a new #NMConnection of the given type, automatically
+ * creating a UUID and an appropriate not-currently-in-use connection
+ * name, setting #NMSettingConnection:autoconnect appropriately for
+ * the connection type, filling in slave-related information if
+ * @master is not %NULL, and initializing any other mandatory-to-set
+ * properties to reasonable initial values.
+ *
+ * Returns: a new #NMConnection
+ */
+NMConnection *
+nm_editor_utils_create_connection (GType         type,
+                                   NMConnection *master,
+                                   NMClient     *client)
+{
+	NMEditorConnectionTypeData **types;
+	NMEditorConnectionTypeDataReal *type_data = NULL;
+	const char *master_setting_type = NULL, *master_uuid = NULL;
+	GType master_type = G_TYPE_INVALID, slave_setting_type = G_TYPE_INVALID;
+	NMConnection *connection;
+	NMSettingConnection *s_con;
+	NMSetting *s_hw, *s_slave;
+	char *uuid, *id;
+	int i;
+
+	if (master) {
+		NMSettingConnection *master_s_con;
+
+		master_s_con = nm_connection_get_setting_connection (master);
+		master_setting_type = nm_setting_connection_get_connection_type (master_s_con);
+		master_uuid = nm_setting_connection_get_uuid (master_s_con);
+		master_type = nm_setting_lookup_type (master_setting_type);
+	}
+
+	types = nm_editor_utils_get_connection_type_list ();
+	for (i = 0; types[i]; i++) {
+		if (types[i]->setting_type == type)
+			type_data = (NMEditorConnectionTypeDataReal *)types[i];
+		if (types[i]->setting_type == master_type)
+			slave_setting_type = types[i]->slave_setting_type;
+
+	}
+	if (!type_data) {
+		g_return_val_if_reached (NULL);
+		return NULL;
+	}
+
+	connection = nm_simple_connection_new ();
+
+	s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ());
+	nm_connection_add_setting (connection, NM_SETTING (s_con));
+
+	s_hw = g_object_new (type, NULL);
+	nm_connection_add_setting (connection, s_hw);
+
+	if (slave_setting_type != G_TYPE_INVALID) {
+		s_slave = g_object_new (slave_setting_type, NULL);
+		nm_connection_add_setting (connection, s_slave);
+	}
+
+	uuid = nm_utils_uuid_generate ();
+	id = get_available_connection_name (type_data->id_format, client);
+
+	g_object_set (s_con,
+	              NM_SETTING_CONNECTION_UUID, uuid,
+	              NM_SETTING_CONNECTION_ID, id,
+	              NM_SETTING_CONNECTION_TYPE, nm_setting_get_name (s_hw),
+	              NM_SETTING_CONNECTION_AUTOCONNECT, !type_data->no_autoconnect,
+	              NM_SETTING_CONNECTION_MASTER, master_uuid,
+	              NM_SETTING_CONNECTION_SLAVE_TYPE, master_setting_type,
+	              NULL);
+
+	g_free (uuid);
+	g_free (id);
+
+	if (type_data->connection_setup_func)
+		type_data->connection_setup_func (connection, s_con, s_hw);
+
+	return connection;
+}
+
+/**
+ * nm_editor_utils_get_connection_type_data:
+ * @conn: an #NMConnection
+ *
+ * Gets the #NMEditorConnectionTypeData corresponding to
+ * @conn's connection type.
+ *
+ * Returns: the #NMEditorConnectionTypeData
+ */
+NMEditorConnectionTypeData *
+nm_editor_utils_get_connection_type_data (NMConnection *conn)
+{
+	NMSettingConnection *s_con;
+	const char *conn_type;
+	GType conn_gtype;
+	NMEditorConnectionTypeData **types;
+	int i;
+
+	s_con = nm_connection_get_setting_connection (conn);
+	g_return_val_if_fail (s_con != NULL, NULL);
+
+	conn_type = nm_setting_connection_get_connection_type (s_con);
+	conn_gtype = nm_setting_lookup_type (conn_type);
+	g_return_val_if_fail (conn_gtype != G_TYPE_INVALID, NULL);
+
+	types = nm_editor_utils_get_connection_type_list ();
+	for (i = 0; types[i]; i++) {
+		if (types[i]->setting_type == conn_gtype)
+			return types[i];
+	}
+
+	return NULL;
+}