summaryrefslogtreecommitdiff
path: root/tui/nm-editor-utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'tui/nm-editor-utils.c')
-rw-r--r--tui/nm-editor-utils.c423
1 files changed, 423 insertions, 0 deletions
diff --git a/tui/nm-editor-utils.c b/tui/nm-editor-utils.c
new file mode 100644
index 000000000..4ac0eb641
--- /dev/null
+++ b/tui/nm-editor-utils.c
@@ -0,0 +1,423 @@
+/* -*- 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 <nm-utils.h>
+
+#include <nm-device-bond.h>
+#include <nm-device-bridge.h>
+#include <nm-device-team.h>
+#include <nm-device-ethernet.h>
+#include <nm-device-infiniband.h>
+#include <nm-device-team.h>
+#include <nm-device-vlan.h>
+#include <nm-device-wifi.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);
+
+ 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);
+#endif
+
+ 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,
+ NMRemoteSettings *settings)
+{
+ GSList *connections, *iter, *names = NULL;
+ char *cname = NULL;
+ int i = 0;
+
+ connections = nm_remote_settings_list_connections (settings);
+ for (iter = connections; iter; iter = iter->next) {
+ const char *id;
+
+ id = nm_connection_get_id (NM_CONNECTION (iter->data));
+ g_assert (id);
+ names = g_slist_append (names, (gpointer) id);
+ }
+ g_slist_free (connections);
+
+ /* Find the next available unique connection name */
+ while (!cname && (i++ < 10000)) {
+ 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
+ * @settings: an #NMRemoteSettings
+ *
+ * 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,
+ NMRemoteSettings *settings)
+{
+ 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_connection_lookup_setting_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_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, settings);
+
+ 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_connection_lookup_setting_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;
+}