Blame src/connection-editor/ce-page.c

Packit Service d328f3
// SPDX-License-Identifier: GPL-2.0+
Packit Service d328f3
/* NetworkManager Connection editor -- Connection editor for NetworkManager
Packit Service d328f3
 *
Packit Service d328f3
 * Dan Williams <dcbw@redhat.com>
Packit Service d328f3
 *
Packit Service d328f3
 * Copyright 2008 - 2014 Red Hat, Inc.
Packit Service d328f3
 */
Packit Service d328f3
Packit Service d328f3
#include "nm-default.h"
Packit Service d328f3
Packit Service d328f3
#include <net/ethernet.h>
Packit Service d328f3
#include <netinet/ether.h>
Packit Service d328f3
#include <string.h>
Packit Service d328f3
#include <stdlib.h>
Packit Service d328f3
Packit Service d328f3
#include "ce-page.h"
Packit Service d328f3
Packit Service d328f3
G_DEFINE_ABSTRACT_TYPE (CEPage, ce_page, G_TYPE_OBJECT)
Packit Service d328f3
Packit Service d328f3
enum {
Packit Service d328f3
	PROP_0,
Packit Service d328f3
	PROP_CONNECTION,
Packit Service d328f3
	PROP_PARENT_WINDOW,
Packit Service d328f3
Packit Service d328f3
	LAST_PROP
Packit Service d328f3
};
Packit Service d328f3
Packit Service d328f3
enum {
Packit Service d328f3
	CHANGED,
Packit Service d328f3
	INITIALIZED,
Packit Service d328f3
	NEW_EDITOR,
Packit Service d328f3
Packit Service d328f3
	LAST_SIGNAL
Packit Service d328f3
};
Packit Service d328f3
Packit Service d328f3
static guint signals[LAST_SIGNAL] = { 0 };
Packit Service d328f3
Packit Service d328f3
typedef struct {
Packit Service d328f3
	int value;
Packit Service d328f3
	const char *text;
Packit Service d328f3
} SpinMapping;
Packit Service d328f3
Packit Service d328f3
static gboolean
Packit Service d328f3
spin_output_with_mapping (GtkSpinButton *spin,
Packit Service d328f3
                          const SpinMapping *mapping)
Packit Service d328f3
{
Packit Service d328f3
	int val;
Packit Service d328f3
	gchar *buf = NULL;
Packit Service d328f3
Packit Service d328f3
	val = gtk_spin_button_get_value_as_int (spin);
Packit Service d328f3
	if (val == mapping->value)
Packit Service d328f3
		buf = g_strdup (mapping->text);
Packit Service d328f3
	else
Packit Service d328f3
		buf = g_strdup_printf ("%d", val);
Packit Service d328f3
Packit Service d328f3
	if (!nm_streq (buf, gtk_entry_get_text (GTK_ENTRY (spin))))
Packit Service d328f3
		gtk_entry_set_text (GTK_ENTRY (spin), buf);
Packit Service d328f3
Packit Service d328f3
	g_free (buf);
Packit Service d328f3
	return TRUE;
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
static gint
Packit Service d328f3
spin_input_with_mapping (GtkSpinButton *spin,
Packit Service d328f3
                         gdouble *new_val,
Packit Service d328f3
                         const SpinMapping *mapping)
Packit Service d328f3
{
Packit Service d328f3
	const gchar *buf;
Packit Service d328f3
Packit Service d328f3
	buf = gtk_entry_get_text (GTK_ENTRY (spin));
Packit Service d328f3
	if (nm_streq (buf, mapping->text)) {
Packit Service d328f3
		*new_val = mapping->value;
Packit Service d328f3
		return TRUE;
Packit Service d328f3
	}
Packit Service d328f3
Packit Service d328f3
	return FALSE;
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
static void
Packit Service d328f3
spin_set_mapping (GtkSpinButton *spin, int value, const char *text)
Packit Service d328f3
{
Packit Service d328f3
	SpinMapping *mapping;
Packit Service d328f3
Packit Service d328f3
	g_return_if_fail (!g_object_get_data (G_OBJECT (spin), "mapping"));
Packit Service d328f3
Packit Service d328f3
	mapping = g_new (SpinMapping, 1);
Packit Service d328f3
	*mapping = (SpinMapping) {
Packit Service d328f3
		.value = value,
Packit Service d328f3
		.text = text,
Packit Service d328f3
	};
Packit Service d328f3
Packit Service d328f3
	g_object_set_data_full (G_OBJECT (spin), "mapping", mapping, g_free);
Packit Service d328f3
Packit Service d328f3
	g_signal_connect (spin, "output",
Packit Service d328f3
	                  G_CALLBACK (spin_output_with_mapping),
Packit Service d328f3
	                  mapping);
Packit Service d328f3
	g_signal_connect (spin, "input",
Packit Service d328f3
	                  G_CALLBACK (spin_input_with_mapping),
Packit Service d328f3
	                  mapping);
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
void
Packit Service d328f3
ce_spin_automatic_val (GtkSpinButton *spin, int defvalue)
Packit Service d328f3
{
Packit Service d328f3
	spin_set_mapping (spin, defvalue, _("automatic"));
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
void
Packit Service d328f3
ce_spin_default_val (GtkSpinButton *spin, int defvalue)
Packit Service d328f3
{
Packit Service d328f3
	spin_set_mapping (spin, defvalue, _("default"));
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
void
Packit Service d328f3
ce_spin_off_val (GtkSpinButton *spin, int defvalue)
Packit Service d328f3
{
Packit Service d328f3
	spin_set_mapping (spin, defvalue, _("off"));
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
int
Packit Service d328f3
ce_get_property_default (NMSetting *setting, const char *property_name)
Packit Service d328f3
{
Packit Service d328f3
	GParamSpec *spec;
Packit Service d328f3
	GValue value = { 0, };
Packit Service d328f3
Packit Service d328f3
	g_return_val_if_fail (NM_IS_SETTING (setting), -1);
Packit Service d328f3
Packit Service d328f3
	spec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), property_name);
Packit Service d328f3
	g_return_val_if_fail (spec != NULL, -1);
Packit Service d328f3
Packit Service d328f3
	g_value_init (&value, spec->value_type);
Packit Service d328f3
	g_param_value_set_default (spec, &value);
Packit Service d328f3
Packit Service d328f3
	if (G_VALUE_HOLDS_CHAR (&value))
Packit Service d328f3
		return (int) g_value_get_schar (&value);
Packit Service d328f3
	else if (G_VALUE_HOLDS_INT (&value))
Packit Service d328f3
		return g_value_get_int (&value);
Packit Service d328f3
	else if (G_VALUE_HOLDS_INT64 (&value))
Packit Service d328f3
		return (int) g_value_get_int64 (&value);
Packit Service d328f3
	else if (G_VALUE_HOLDS_LONG (&value))
Packit Service d328f3
		return (int) g_value_get_long (&value);
Packit Service d328f3
	else if (G_VALUE_HOLDS_UINT (&value))
Packit Service d328f3
		return (int) g_value_get_uint (&value);
Packit Service d328f3
	else if (G_VALUE_HOLDS_UINT64 (&value))
Packit Service d328f3
		return (int) g_value_get_uint64 (&value);
Packit Service d328f3
	else if (G_VALUE_HOLDS_ULONG (&value))
Packit Service d328f3
		return (int) g_value_get_ulong (&value);
Packit Service d328f3
	else if (G_VALUE_HOLDS_UCHAR (&value))
Packit Service d328f3
		return (int) g_value_get_uchar (&value);
Packit Service d328f3
	g_return_val_if_fail (FALSE, 0);
Packit Service d328f3
	return 0;
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
gboolean
Packit Service d328f3
ce_page_validate (CEPage *self, NMConnection *connection, GError **error)
Packit Service d328f3
{
Packit Service d328f3
	g_return_val_if_fail (CE_IS_PAGE (self), FALSE);
Packit Service d328f3
	g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
Packit Service d328f3
Packit Service d328f3
	if (CE_PAGE_GET_CLASS (self)->ce_page_validate_v) {
Packit Service d328f3
		if (!CE_PAGE_GET_CLASS (self)->ce_page_validate_v (self, connection, error)) {
Packit Service d328f3
			if (error && !*error)
Packit Service d328f3
				g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("unspecified error"));
Packit Service d328f3
			return FALSE;
Packit Service d328f3
		}
Packit Service d328f3
	}
Packit Service d328f3
Packit Service d328f3
	return TRUE;
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
gboolean
Packit Service d328f3
ce_page_last_update (CEPage *self, NMConnection *connection, GError **error)
Packit Service d328f3
{
Packit Service d328f3
	g_return_val_if_fail (CE_IS_PAGE (self), FALSE);
Packit Service d328f3
	g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
Packit Service d328f3
Packit Service d328f3
	if (CE_PAGE_GET_CLASS (self)->last_update)
Packit Service d328f3
		return CE_PAGE_GET_CLASS (self)->last_update (self, connection, error);
Packit Service d328f3
Packit Service d328f3
	return TRUE;
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
gboolean
Packit Service d328f3
ce_page_inter_page_change (CEPage *self)
Packit Service d328f3
{
Packit Service d328f3
	gboolean ret = FALSE;
Packit Service d328f3
Packit Service d328f3
	g_return_val_if_fail (CE_IS_PAGE (self), FALSE);
Packit Service d328f3
Packit Service d328f3
	if (self->inter_page_change_running)
Packit Service d328f3
		return FALSE;
Packit Service d328f3
Packit Service d328f3
	self->inter_page_change_running = TRUE;
Packit Service d328f3
	if (CE_PAGE_GET_CLASS (self)->inter_page_change)
Packit Service d328f3
		ret = CE_PAGE_GET_CLASS (self)->inter_page_change (self);
Packit Service d328f3
	self->inter_page_change_running = FALSE;
Packit Service d328f3
Packit Service d328f3
	return ret;
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
static void
Packit Service d328f3
_set_active_combo_item (GtkComboBox *combo, const char *item,
Packit Service d328f3
                        const char *combo_item, int combo_idx)
Packit Service d328f3
{
Packit Service d328f3
	GtkWidget *entry;
Packit Service d328f3
Packit Service d328f3
	if (item) {
Packit Service d328f3
		/* set active item */
Packit Service d328f3
		gtk_combo_box_set_active (combo, combo_idx);
Packit Service d328f3
Packit Service d328f3
		if (!combo_item)
Packit Service d328f3
			gtk_combo_box_text_prepend_text (GTK_COMBO_BOX_TEXT (combo), item);
Packit Service d328f3
Packit Service d328f3
		entry = gtk_bin_get_child (GTK_BIN (combo));
Packit Service d328f3
		if (entry)
Packit Service d328f3
			gtk_entry_set_text (GTK_ENTRY (entry), combo_item ? combo_item : item);
Packit Service d328f3
	}
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
/* Combo box storing data in the form of "text1 (text2)" */
Packit Service d328f3
void
Packit Service d328f3
ce_page_setup_data_combo (CEPage *self, GtkComboBox *combo,
Packit Service d328f3
                          const char *data, char **list)
Packit Service d328f3
{
Packit Service d328f3
	char **iter, *active_item = NULL;
Packit Service d328f3
	int i, active_idx = -1;
Packit Service d328f3
	int data_len;
Packit Service d328f3
Packit Service d328f3
	if (data)
Packit Service d328f3
		data_len = strlen (data);
Packit Service d328f3
	else
Packit Service d328f3
		data_len = -1;
Packit Service d328f3
Packit Service d328f3
	for (iter = list, i = 0; iter && *iter; iter++, i++) {
Packit Service d328f3
		gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), *iter);
Packit Service d328f3
		if (   data
Packit Service d328f3
		    && g_ascii_strncasecmp (*iter, data, data_len) == 0
Packit Service d328f3
		    && ((*iter)[data_len] == '\0' || (*iter)[data_len] == ' ')) {
Packit Service d328f3
			active_item = *iter;
Packit Service d328f3
			active_idx = i;
Packit Service d328f3
		}
Packit Service d328f3
	}
Packit Service d328f3
	_set_active_combo_item (combo, data, active_item, active_idx);
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
/* Combo box storing MAC addresses only */
Packit Service d328f3
void
Packit Service d328f3
ce_page_setup_mac_combo (CEPage *self, GtkComboBox *combo,
Packit Service d328f3
                         const char *mac, char **mac_list)
Packit Service d328f3
{
Packit Service d328f3
	char **iter, *active_mac = NULL;
Packit Service d328f3
	int i, active_idx = -1;
Packit Service d328f3
Packit Service d328f3
	for (iter = mac_list, i = 0; iter && *iter; iter++, i++) {
Packit Service d328f3
		gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), *iter);
Packit Service d328f3
		if (mac && *iter && nm_utils_hwaddr_matches (mac, -1, *iter, -1)) {
Packit Service d328f3
			active_mac = *iter;
Packit Service d328f3
			active_idx = i;
Packit Service d328f3
		}
Packit Service d328f3
	}
Packit Service d328f3
	_set_active_combo_item (combo, mac, active_mac, active_idx);
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
void
Packit Service d328f3
ce_page_setup_cloned_mac_combo (GtkComboBoxText *combo, const char *current)
Packit Service d328f3
{
Packit Service d328f3
	GtkWidget *entry;
Packit Service d328f3
	static const char *entries[][2] = { { "preserve",  N_("Preserve") },
Packit Service d328f3
	                                    { "permanent", N_("Permanent") },
Packit Service d328f3
	                                    { "random",    N_("Random") },
Packit Service d328f3
	                                    { "stable",    N_("Stable") } };
Packit Service d328f3
	int i, active = -1;
Packit Service d328f3
Packit Service d328f3
	gtk_widget_set_tooltip_text (GTK_WIDGET (combo),
Packit Service d328f3
		_("The MAC address entered here will be used as hardware address for "
Packit Service d328f3
		  "the network device this connection is activated on. This feature is "
Packit Service d328f3
		  "known as MAC cloning or spoofing. Example: 00:11:22:33:44:55"));
Packit Service d328f3
Packit Service d328f3
	gtk_combo_box_text_remove_all (combo);
Packit Service d328f3
Packit Service d328f3
	for (i = 0; i < G_N_ELEMENTS (entries); i++) {
Packit Service d328f3
		gtk_combo_box_text_append (combo, entries[i][0], _(entries[i][1]));
Packit Service d328f3
		if (nm_streq0 (current, entries[i][0]))
Packit Service d328f3
			active = i;
Packit Service d328f3
	}
Packit Service d328f3
Packit Service d328f3
	if (active != -1) {
Packit Service d328f3
		gtk_combo_box_set_active (GTK_COMBO_BOX (combo), active);
Packit Service d328f3
	} else if (current && current[0]) {
Packit Service d328f3
		entry = gtk_bin_get_child (GTK_BIN (combo));
Packit Service d328f3
		g_assert (entry);
Packit Service d328f3
		gtk_entry_set_text (GTK_ENTRY (entry), current);
Packit Service d328f3
	}
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
char *
Packit Service d328f3
ce_page_cloned_mac_get (GtkComboBoxText *combo)
Packit Service d328f3
{
Packit Service d328f3
	const char *id;
Packit Service d328f3
Packit Service d328f3
	id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (combo));
Packit Service d328f3
	if (id)
Packit Service d328f3
		return g_strdup (id);
Packit Service d328f3
Packit Service d328f3
	return gtk_combo_box_text_get_active_text (combo);
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
static gboolean
Packit Service d328f3
mac_valid (const char *mac, int type, const char *property_name, GError **error)
Packit Service d328f3
{
Packit Service d328f3
	if (mac && *mac) {
Packit Service d328f3
		if (!nm_utils_hwaddr_valid (mac, nm_utils_hwaddr_len (type))) {
Packit Service d328f3
			const char *addr_type;
Packit Service d328f3
Packit Service d328f3
			addr_type = type == ARPHRD_ETHER ? _("MAC address") : _("HW address");
Packit Service d328f3
			if (property_name) {
Packit Service d328f3
				g_set_error (error, NMA_ERROR, NMA_ERROR_GENERIC,
Packit Service d328f3
				             _("invalid %s for %s (%s)"),
Packit Service d328f3
				             addr_type, property_name, mac);
Packit Service d328f3
			} else {
Packit Service d328f3
				g_set_error (error, NMA_ERROR, NMA_ERROR_GENERIC,
Packit Service d328f3
				             _("invalid %s (%s)"),
Packit Service d328f3
				             addr_type, mac);
Packit Service d328f3
			}
Packit Service d328f3
			return FALSE;
Packit Service d328f3
		}
Packit Service d328f3
	}
Packit Service d328f3
Packit Service d328f3
	return TRUE;
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
gboolean
Packit Service d328f3
ce_page_cloned_mac_combo_valid (GtkComboBoxText *combo, int type, const char *property_name, GError **error)
Packit Service d328f3
{
Packit Service d328f3
	gs_free char *text = NULL;
Packit Service d328f3
Packit Service d328f3
	if (gtk_combo_box_get_active (GTK_COMBO_BOX (combo)) != -1)
Packit Service d328f3
		return TRUE;
Packit Service d328f3
Packit Service d328f3
	text = gtk_combo_box_text_get_active_text (combo);
Packit Service d328f3
	return mac_valid (text,
Packit Service d328f3
	                  type,
Packit Service d328f3
	                  property_name,
Packit Service d328f3
	                  error);
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
gboolean
Packit Service d328f3
ce_page_mac_entry_valid (GtkEntry *entry, int type, const char *property_name, GError **error)
Packit Service d328f3
{
Packit Service d328f3
	g_return_val_if_fail (GTK_IS_ENTRY (entry), FALSE);
Packit Service d328f3
Packit Service d328f3
	return mac_valid (gtk_entry_get_text (entry), type, property_name, error);
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
gboolean
Packit Service d328f3
ce_page_interface_name_valid (const char *iface, const char *property_name, GError **error)
Packit Service d328f3
{
Packit Service d328f3
	if (iface && *iface) {
Packit Service d328f3
		if (!nm_utils_is_valid_iface_name (iface, error)) {
Packit Service d328f3
			if (property_name) {
Packit Service d328f3
				g_prefix_error (error,
Packit Service d328f3
				                _("invalid interface-name for %s (%s): "),
Packit Service d328f3
				                property_name, iface);
Packit Service d328f3
			} else {
Packit Service d328f3
				g_prefix_error (error,
Packit Service d328f3
				                _("invalid interface-name (%s): "),
Packit Service d328f3
				                iface);
Packit Service d328f3
			}
Packit Service d328f3
			return FALSE;
Packit Service d328f3
		}
Packit Service d328f3
	}
Packit Service d328f3
	return TRUE;
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
static char **
Packit Service d328f3
_get_device_list (CEPage *self,
Packit Service d328f3
                  GType device_type,
Packit Service d328f3
                  gboolean set_ifname,
Packit Service d328f3
                  const char *mac_property)
Packit Service d328f3
{
Packit Service d328f3
	const GPtrArray *devices;
Packit Service d328f3
	GPtrArray *interfaces;
Packit Service d328f3
	int i;
Packit Service d328f3
Packit Service d328f3
	g_return_val_if_fail (CE_IS_PAGE (self), NULL);
Packit Service d328f3
	g_return_val_if_fail (set_ifname || mac_property, NULL);
Packit Service d328f3
Packit Service d328f3
	if (!self->client)
Packit Service d328f3
		return NULL;
Packit Service d328f3
Packit Service d328f3
	interfaces = g_ptr_array_new ();
Packit Service d328f3
	devices = nm_client_get_devices (self->client);
Packit Service d328f3
	for (i = 0; i < devices->len; i++) {
Packit Service d328f3
		NMDevice *dev = g_ptr_array_index (devices, i);
Packit Service d328f3
		const char *ifname;
Packit Service d328f3
		char *mac = NULL;
Packit Service d328f3
		char *item;
Packit Service d328f3
Packit Service d328f3
		if (   device_type != G_TYPE_NONE
Packit Service d328f3
		    && !G_TYPE_CHECK_INSTANCE_TYPE (dev, device_type))
Packit Service d328f3
			continue;
Packit Service d328f3
Packit Service d328f3
		if (device_type == NM_TYPE_DEVICE_BT)
Packit Service d328f3
			ifname = nm_device_bt_get_name (NM_DEVICE_BT (dev));
Packit Service d328f3
		else
Packit Service d328f3
			ifname = nm_device_get_iface (NM_DEVICE (dev));
Packit Service d328f3
		if (mac_property)
Packit Service d328f3
			g_object_get (G_OBJECT (dev), mac_property, &mac, NULL);
Packit Service d328f3
Packit Service d328f3
		if (mac && !mac[0])
Packit Service d328f3
			nm_clear_g_free (&mac);
Packit Service d328f3
Packit Service d328f3
		if (set_ifname && mac_property)
Packit Service d328f3
			item = g_strdup_printf ("%s%s%s%s", ifname, NM_PRINT_FMT_QUOTED (mac, " (", mac, ")", ""));
Packit Service d328f3
		else
Packit Service d328f3
			item = g_strdup (set_ifname ? ifname : mac);
Packit Service d328f3
Packit Service d328f3
		if (item)
Packit Service d328f3
			g_ptr_array_add (interfaces, item);
Packit Service d328f3
Packit Service d328f3
		g_free (mac);
Packit Service d328f3
	}
Packit Service d328f3
	g_ptr_array_add (interfaces, NULL);
Packit Service d328f3
Packit Service d328f3
	return (char **)g_ptr_array_free (interfaces, FALSE);
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
static gboolean
Packit Service d328f3
_device_entry_parse (const char *entry_text, char **first, char **second)
Packit Service d328f3
{
Packit Service d328f3
	const char *sp, *left, *right;
Packit Service d328f3
Packit Service d328f3
	if (!entry_text || !*entry_text) {
Packit Service d328f3
		*first = NULL;
Packit Service d328f3
		*second = NULL;
Packit Service d328f3
		return TRUE;
Packit Service d328f3
	}
Packit Service d328f3
Packit Service d328f3
	sp = strstr (entry_text, " (");
Packit Service d328f3
	if (sp) {
Packit Service d328f3
		*first = g_strndup (entry_text, sp - entry_text);
Packit Service d328f3
		left = sp + 1;
Packit Service d328f3
		right = strchr (left, ')');
Packit Service d328f3
		if (*left == '(' && right && right > left)
Packit Service d328f3
			*second = g_strndup (left + 1, right - left - 1);
Packit Service d328f3
		else {
Packit Service d328f3
			*second = NULL;
Packit Service d328f3
			return FALSE;
Packit Service d328f3
		}
Packit Service d328f3
	} else {
Packit Service d328f3
		*first = g_strdup (entry_text);
Packit Service d328f3
		*second = NULL;
Packit Service d328f3
	}
Packit Service d328f3
	return TRUE;
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
static gboolean
Packit Service d328f3
_device_entries_match (const char *ifname, const char *mac, const char *entry)
Packit Service d328f3
{
Packit Service d328f3
	char *first, *second;
Packit Service d328f3
	gboolean ifname_match = FALSE, mac_match = FALSE;
Packit Service d328f3
	gboolean both;
Packit Service d328f3
Packit Service d328f3
	if (!ifname && !mac)
Packit Service d328f3
		return FALSE;
Packit Service d328f3
Packit Service d328f3
	_device_entry_parse (entry, &first, &second);
Packit Service d328f3
	both = first && second;
Packit Service d328f3
Packit Service d328f3
	if (   ifname
Packit Service d328f3
	    && (   !g_strcmp0 (ifname, first)
Packit Service d328f3
	        || !g_strcmp0 (ifname, second)))
Packit Service d328f3
		ifname_match = TRUE;
Packit Service d328f3
Packit Service d328f3
	if (   mac
Packit Service d328f3
	    && (   (first && nm_utils_hwaddr_matches (mac, -1, first, -1))
Packit Service d328f3
	        || (second && nm_utils_hwaddr_matches (mac, -1, second, -1))))
Packit Service d328f3
		mac_match = TRUE;
Packit Service d328f3
Packit Service d328f3
	g_free (first);
Packit Service d328f3
	g_free (second);
Packit Service d328f3
Packit Service d328f3
	if (both)
Packit Service d328f3
		return ifname_match && mac_match;
Packit Service d328f3
	else {
Packit Service d328f3
		if (ifname)
Packit Service d328f3
			return ifname_match;
Packit Service d328f3
		else
Packit Service d328f3
			return mac_match;
Packit Service d328f3
	}
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
/* Combo box storing ifname and/or MAC */
Packit Service d328f3
void
Packit Service d328f3
ce_page_setup_device_combo (CEPage *self,
Packit Service d328f3
                            GtkComboBox *combo,
Packit Service d328f3
                            GType device_type,
Packit Service d328f3
                            const char *ifname,
Packit Service d328f3
                            const char *mac,
Packit Service d328f3
                            const char *mac_property)
Packit Service d328f3
{
Packit Service d328f3
	char **iter, *active_item = NULL;
Packit Service d328f3
	int i, active_idx = -1;
Packit Service d328f3
	char **device_list;
Packit Service d328f3
	char *item;
Packit Service d328f3
Packit Service d328f3
	device_list = _get_device_list (self, device_type, TRUE, mac_property);
Packit Service d328f3
Packit Service d328f3
	if (ifname && mac)
Packit Service d328f3
		item = g_strdup_printf ("%s (%s)", ifname, mac);
Packit Service d328f3
	else if (!ifname && !mac)
Packit Service d328f3
		item = NULL;
Packit Service d328f3
	else
Packit Service d328f3
		item = g_strdup (ifname ? ifname : mac);
Packit Service d328f3
Packit Service d328f3
	for (iter = device_list, i = 0; iter && *iter; iter++, i++) {
Packit Service d328f3
		gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), *iter);
Packit Service d328f3
		if (_device_entries_match (ifname, mac, *iter)) {
Packit Service d328f3
			active_item = *iter;
Packit Service d328f3
			active_idx = i;
Packit Service d328f3
		}
Packit Service d328f3
	}
Packit Service d328f3
	_set_active_combo_item (combo, item, active_item, active_idx);
Packit Service d328f3
Packit Service d328f3
	g_free (item);
Packit Service d328f3
	g_strfreev (device_list);
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
gboolean
Packit Service d328f3
ce_page_device_entry_get (GtkEntry *entry, int type, gboolean check_ifname,
Packit Service d328f3
                          char **ifname, char **mac, const char *device_name, GError **error)
Packit Service d328f3
{
Packit Service d328f3
	gs_free char *first = NULL;
Packit Service d328f3
	gs_free char *second = NULL;
Packit Service d328f3
	const char *ifname_tmp = NULL, *mac_tmp = NULL;
Packit Service d328f3
	const char *str;
Packit Service d328f3
Packit Service d328f3
	g_return_val_if_fail (entry != NULL, FALSE);
Packit Service d328f3
	g_return_val_if_fail (GTK_IS_ENTRY (entry), FALSE);
Packit Service d328f3
Packit Service d328f3
	str = gtk_entry_get_text (entry);
Packit Service d328f3
Packit Service d328f3
	if (!_device_entry_parse (str, &first, &second)) {
Packit Service d328f3
		g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC,
Packit Service d328f3
		                     _("can’t parse device name"));
Packit Service d328f3
		goto invalid;
Packit Service d328f3
	}
Packit Service d328f3
Packit Service d328f3
	if (first) {
Packit Service d328f3
		if (nm_utils_hwaddr_valid (first, nm_utils_hwaddr_len (type)))
Packit Service d328f3
			mac_tmp = first;
Packit Service d328f3
		else if (!check_ifname || nm_utils_is_valid_iface_name (first, error))
Packit Service d328f3
			ifname_tmp = first;
Packit Service d328f3
		else
Packit Service d328f3
			goto invalid;
Packit Service d328f3
	}
Packit Service d328f3
	if (second) {
Packit Service d328f3
		if (nm_utils_hwaddr_valid (second, nm_utils_hwaddr_len (type))) {
Packit Service d328f3
			if (!mac_tmp) {
Packit Service d328f3
				mac_tmp = second;
Packit Service d328f3
			} else {
Packit Service d328f3
				g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC,
Packit Service d328f3
				                     _("invalid hardware address"));
Packit Service d328f3
				goto invalid;
Packit Service d328f3
			}
Packit Service d328f3
		} else if (!check_ifname || nm_utils_is_valid_iface_name (second, error)) {
Packit Service d328f3
			if (!ifname_tmp)
Packit Service d328f3
				ifname_tmp = second;
Packit Service d328f3
			else
Packit Service d328f3
				goto invalid;
Packit Service d328f3
		} else
Packit Service d328f3
			goto invalid;
Packit Service d328f3
	}
Packit Service d328f3
Packit Service d328f3
	if (ifname)
Packit Service d328f3
		*ifname = g_strdup (ifname_tmp);
Packit Service d328f3
	if (mac)
Packit Service d328f3
		*mac = g_strdup (mac_tmp);
Packit Service d328f3
Packit Service d328f3
	return TRUE;
Packit Service d328f3
Packit Service d328f3
invalid:
Packit Service d328f3
	if (error) {
Packit Service d328f3
		g_prefix_error (error,
Packit Service d328f3
		                _("invalid %s (%s): "),
Packit Service d328f3
		                device_name ? device_name : _("device"),
Packit Service d328f3
		                str);
Packit Service d328f3
	} else {
Packit Service d328f3
		g_set_error (error, NMA_ERROR, NMA_ERROR_GENERIC,
Packit Service d328f3
		             _("invalid %s (%s) "),
Packit Service d328f3
		            device_name ? device_name : _("device"),
Packit Service d328f3
		            str);
Packit Service d328f3
	}
Packit Service d328f3
Packit Service d328f3
	return FALSE;
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
char *
Packit Service d328f3
ce_page_get_next_available_name (const GPtrArray *connections, const char *format)
Packit Service d328f3
{
Packit Service d328f3
	GSList *names = NULL, *iter;
Packit Service d328f3
	char *cname = NULL;
Packit Service d328f3
	int i = 0;
Packit Service d328f3
Packit Service d328f3
	for (i = 0; i < connections->len; i++) {
Packit Service d328f3
		const char *id;
Packit Service d328f3
Packit Service d328f3
		id = nm_connection_get_id (connections->pdata[i]);
Packit Service d328f3
		g_assert (id);
Packit Service d328f3
		names = g_slist_append (names, (gpointer) id);
Packit Service d328f3
	}
Packit Service d328f3
Packit Service d328f3
	/* Find the next available unique connection name */
Packit Service d328f3
	for (i = 1; !cname && i < 10000; i++) {
Packit Service d328f3
		char *temp;
Packit Service d328f3
		gboolean found = FALSE;
Packit Service d328f3
Packit Service d328f3
		NM_PRAGMA_WARNING_DISABLE("-Wformat-nonliteral")
Packit Service d328f3
		temp = g_strdup_printf (format, i);
Packit Service d328f3
		NM_PRAGMA_WARNING_REENABLE
Packit Service d328f3
		for (iter = names; iter; iter = g_slist_next (iter)) {
Packit Service d328f3
			if (!strcmp (iter->data, temp)) {
Packit Service d328f3
				found = TRUE;
Packit Service d328f3
				break;
Packit Service d328f3
			}
Packit Service d328f3
		}
Packit Service d328f3
		if (!found)
Packit Service d328f3
			cname = temp;
Packit Service d328f3
		else
Packit Service d328f3
			g_free (temp);
Packit Service d328f3
	}
Packit Service d328f3
Packit Service d328f3
	g_slist_free (names);
Packit Service d328f3
	return cname;
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
void
Packit Service d328f3
ce_page_complete_init (CEPage *self,
Packit Service d328f3
                       const char *setting_name,
Packit Service d328f3
                       GVariant *secrets,
Packit Service d328f3
                       GError *error)
Packit Service d328f3
{
Packit Service d328f3
	GError *update_error = NULL;
Packit Service d328f3
	GVariant *setting_dict;
Packit Service d328f3
	char *dbus_err;
Packit Service d328f3
Packit Service d328f3
	g_return_if_fail (self != NULL);
Packit Service d328f3
	g_return_if_fail (CE_IS_PAGE (self));
Packit Service d328f3
Packit Service d328f3
	if (error) {
Packit Service d328f3
		/* Ignore missing settings errors */
Packit Service d328f3
		dbus_err = g_dbus_error_get_remote_error (error);
Packit Service d328f3
		if (   g_strcmp0 (dbus_err, "org.freedesktop.NetworkManager.Settings.InvalidSetting") == 0
Packit Service d328f3
		    || g_strcmp0 (dbus_err, "org.freedesktop.NetworkManager.Settings.Connection.SettingNotFound") == 0
Packit Service d328f3
		    || g_strcmp0 (dbus_err, "org.freedesktop.NetworkManager.AgentManager.NoSecrets") == 0)
Packit Service d328f3
			g_clear_error (&error);
Packit Service d328f3
		g_free (dbus_err);
Packit Service d328f3
	}
Packit Service d328f3
Packit Service d328f3
	if (error) {
Packit Service d328f3
		g_warning ("Couldn't fetch secrets: %s", error->message);
Packit Service d328f3
		g_error_free (error);
Packit Service d328f3
		goto out;
Packit Service d328f3
	}
Packit Service d328f3
Packit Service d328f3
	if (!setting_name || !secrets || g_variant_n_children (secrets) == 0) {
Packit Service d328f3
		/* Success, no secrets */
Packit Service d328f3
		goto out;
Packit Service d328f3
	}
Packit Service d328f3
Packit Service d328f3
	g_assert (setting_name);
Packit Service d328f3
	g_assert (secrets);
Packit Service d328f3
Packit Service d328f3
	setting_dict = g_variant_lookup_value (secrets, setting_name, NM_VARIANT_TYPE_SETTING);
Packit Service d328f3
	if (!setting_dict) {
Packit Service d328f3
		/* Success, no secrets */
Packit Service d328f3
		goto out;
Packit Service d328f3
	}
Packit Service d328f3
	g_variant_unref (setting_dict);
Packit Service d328f3
Packit Service d328f3
	/* Update the connection with the new secrets */
Packit Service d328f3
	if (!nm_connection_update_secrets (self->connection,
Packit Service d328f3
	                                  setting_name,
Packit Service d328f3
	                                  secrets,
Packit Service d328f3
	                                  &update_error)) {
Packit Service d328f3
		g_warning ("Couldn't update the secrets: %s", update_error->message);
Packit Service d328f3
		g_error_free (update_error);
Packit Service d328f3
		goto out;
Packit Service d328f3
	}
Packit Service d328f3
Packit Service d328f3
out:
Packit Service d328f3
	g_signal_emit (self, signals[INITIALIZED], 0, NULL);
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
static void
Packit Service d328f3
ce_page_init (CEPage *self)
Packit Service d328f3
{
Packit Service d328f3
	self->builder = gtk_builder_new ();
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
static void
Packit Service d328f3
dispose (GObject *object)
Packit Service d328f3
{
Packit Service d328f3
	CEPage *self = CE_PAGE (object);
Packit Service d328f3
Packit Service d328f3
	g_clear_object (&self->page);
Packit Service d328f3
	g_clear_object (&self->builder);
Packit Service d328f3
	g_clear_object (&self->connection);
Packit Service d328f3
Packit Service d328f3
	G_OBJECT_CLASS (ce_page_parent_class)->dispose (object);
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
static void
Packit Service d328f3
finalize (GObject *object)
Packit Service d328f3
{
Packit Service d328f3
	CEPage *self = CE_PAGE (object);
Packit Service d328f3
Packit Service d328f3
	g_free (self->title);
Packit Service d328f3
Packit Service d328f3
	G_OBJECT_CLASS (ce_page_parent_class)->finalize (object);
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
GtkWidget *
Packit Service d328f3
ce_page_get_page (CEPage *self)
Packit Service d328f3
{
Packit Service d328f3
	g_return_val_if_fail (CE_IS_PAGE (self), NULL);
Packit Service d328f3
Packit Service d328f3
	return self->page;
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
const char *
Packit Service d328f3
ce_page_get_title (CEPage *self)
Packit Service d328f3
{
Packit Service d328f3
	g_return_val_if_fail (CE_IS_PAGE (self), NULL);
Packit Service d328f3
Packit Service d328f3
	return self->title;
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
void
Packit Service d328f3
ce_page_changed (CEPage *self)
Packit Service d328f3
{
Packit Service d328f3
	g_return_if_fail (CE_IS_PAGE (self));
Packit Service d328f3
Packit Service d328f3
	g_signal_emit (self, signals[CHANGED], 0);
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
NMConnectionEditor *
Packit Service d328f3
ce_page_new_editor (CEPage *self,
Packit Service d328f3
                    GtkWindow *parent_window,
Packit Service d328f3
                    NMConnection *connection)
Packit Service d328f3
{
Packit Service d328f3
	NMConnectionEditor *editor;
Packit Service d328f3
Packit Service d328f3
	g_return_val_if_fail (CE_IS_PAGE (self), NULL);
Packit Service d328f3
Packit Service d328f3
	editor = nm_connection_editor_new (parent_window,
Packit Service d328f3
	                                   connection,
Packit Service d328f3
	                                   self->client);
Packit Service d328f3
	if (!editor)
Packit Service d328f3
		return NULL;
Packit Service d328f3
Packit Service d328f3
	g_signal_emit (self, signals[NEW_EDITOR], 0, editor);
Packit Service d328f3
	return editor;
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
static void
Packit Service d328f3
get_property (GObject *object, guint prop_id,
Packit Service d328f3
              GValue *value, GParamSpec *pspec)
Packit Service d328f3
{
Packit Service d328f3
	CEPage *self = CE_PAGE (object);
Packit Service d328f3
Packit Service d328f3
	switch (prop_id) {
Packit Service d328f3
	case PROP_CONNECTION:
Packit Service d328f3
		g_value_set_object (value, self->connection);
Packit Service d328f3
		break;
Packit Service d328f3
	default:
Packit Service d328f3
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
Packit Service d328f3
		break;
Packit Service d328f3
	}
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
static void
Packit Service d328f3
set_property (GObject *object, guint prop_id,
Packit Service d328f3
              const GValue *value, GParamSpec *pspec)
Packit Service d328f3
{
Packit Service d328f3
	CEPage *self = CE_PAGE (object);
Packit Service d328f3
Packit Service d328f3
	switch (prop_id) {
Packit Service d328f3
	case PROP_CONNECTION:
Packit Service d328f3
		if (self->connection)
Packit Service d328f3
			g_object_unref (self->connection);
Packit Service d328f3
		self->connection = g_value_dup_object (value);
Packit Service d328f3
		break;
Packit Service d328f3
	case PROP_PARENT_WINDOW:
Packit Service d328f3
		self->parent_window = g_value_get_pointer (value);
Packit Service d328f3
		break;
Packit Service d328f3
	default:
Packit Service d328f3
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
Packit Service d328f3
		break;
Packit Service d328f3
	}
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
static void
Packit Service d328f3
ce_page_class_init (CEPageClass *page_class)
Packit Service d328f3
{
Packit Service d328f3
	GObjectClass *object_class = G_OBJECT_CLASS (page_class);
Packit Service d328f3
Packit Service d328f3
	/* virtual methods */
Packit Service d328f3
	object_class->dispose      = dispose;
Packit Service d328f3
	object_class->finalize     = finalize;
Packit Service d328f3
	object_class->get_property = get_property;
Packit Service d328f3
	object_class->set_property = set_property;
Packit Service d328f3
Packit Service d328f3
	/* Properties */
Packit Service d328f3
	g_object_class_install_property
Packit Service d328f3
		(object_class, PROP_CONNECTION,
Packit Service d328f3
		 g_param_spec_object (CE_PAGE_CONNECTION,
Packit Service d328f3
		                      "Connection",
Packit Service d328f3
		                      "Connection",
Packit Service d328f3
		                      NM_TYPE_CONNECTION,
Packit Service d328f3
		                      G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
Packit Service d328f3
Packit Service d328f3
	g_object_class_install_property
Packit Service d328f3
		(object_class, PROP_PARENT_WINDOW,
Packit Service d328f3
		 g_param_spec_pointer (CE_PAGE_PARENT_WINDOW,
Packit Service d328f3
		                       "Parent window",
Packit Service d328f3
		                       "Parent window",
Packit Service d328f3
		                       G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
Packit Service d328f3
Packit Service d328f3
	/* Signals */
Packit Service d328f3
	signals[CHANGED] = 
Packit Service d328f3
		g_signal_new ("changed",
Packit Service d328f3
	                      G_OBJECT_CLASS_TYPE (object_class),
Packit Service d328f3
	                      G_SIGNAL_RUN_FIRST,
Packit Service d328f3
	                      0, NULL, NULL, NULL,
Packit Service d328f3
	                      G_TYPE_NONE, 0);
Packit Service d328f3
Packit Service d328f3
	signals[INITIALIZED] = 
Packit Service d328f3
		g_signal_new (CE_PAGE_INITIALIZED,
Packit Service d328f3
	                      G_OBJECT_CLASS_TYPE (object_class),
Packit Service d328f3
	                      G_SIGNAL_RUN_FIRST,
Packit Service d328f3
	                      0, NULL, NULL, NULL,
Packit Service d328f3
	                      G_TYPE_NONE, 1, G_TYPE_POINTER);
Packit Service d328f3
Packit Service d328f3
	signals[NEW_EDITOR] =
Packit Service d328f3
		g_signal_new (CE_PAGE_NEW_EDITOR,
Packit Service d328f3
	                      G_OBJECT_CLASS_TYPE (object_class),
Packit Service d328f3
	                      G_SIGNAL_RUN_FIRST,
Packit Service d328f3
	                      0, NULL, NULL, NULL,
Packit Service d328f3
	                      G_TYPE_NONE, 1, G_TYPE_POINTER);
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
Packit Service d328f3
void
Packit Service d328f3
ce_page_complete_connection (NMConnection *connection,
Packit Service d328f3
                             const char *format,
Packit Service d328f3
                             const char *ctype,
Packit Service d328f3
                             gboolean autoconnect,
Packit Service d328f3
                             NMClient *client)
Packit Service d328f3
{
Packit Service d328f3
	NMSettingConnection *s_con;
Packit Service d328f3
	char *id, *uuid;
Packit Service d328f3
	const GPtrArray *connections;
Packit Service d328f3
Packit Service d328f3
	s_con = nm_connection_get_setting_connection (connection);
Packit Service d328f3
	if (!s_con) {
Packit Service d328f3
		s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ());
Packit Service d328f3
		nm_connection_add_setting (connection, NM_SETTING (s_con));
Packit Service d328f3
	}
Packit Service d328f3
Packit Service d328f3
	if (!nm_setting_connection_get_id (s_con)) {
Packit Service d328f3
		connections = nm_client_get_connections (client);
Packit Service d328f3
		id = ce_page_get_next_available_name (connections, format);
Packit Service d328f3
		g_object_set (s_con, NM_SETTING_CONNECTION_ID, id, NULL);
Packit Service d328f3
		g_free (id);
Packit Service d328f3
	}
Packit Service d328f3
Packit Service d328f3
	uuid = nm_utils_uuid_generate ();
Packit Service d328f3
	g_object_set (s_con,
Packit Service d328f3
	              NM_SETTING_CONNECTION_UUID, uuid,
Packit Service d328f3
	              NM_SETTING_CONNECTION_TYPE, ctype,
Packit Service d328f3
	              NM_SETTING_CONNECTION_AUTOCONNECT, autoconnect,
Packit Service d328f3
	              NULL);
Packit Service d328f3
	g_free (uuid);
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
CEPage *
Packit Service d328f3
ce_page_new (GType page_type,
Packit Service d328f3
             NMConnectionEditor *editor,
Packit Service d328f3
             NMConnection *connection,
Packit Service d328f3
             GtkWindow *parent_window,
Packit Service d328f3
             NMClient *client,
Packit Service d328f3
             const char *ui_resource,
Packit Service d328f3
             const char *widget_name,
Packit Service d328f3
             const char *title)
Packit Service d328f3
{
Packit Service d328f3
	CEPage *self;
Packit Service d328f3
	GError *error = NULL;
Packit Service d328f3
Packit Service d328f3
	g_return_val_if_fail (title != NULL, NULL);
Packit Service d328f3
	if (ui_resource)
Packit Service d328f3
		g_return_val_if_fail (widget_name != NULL, NULL);
Packit Service d328f3
Packit Service d328f3
	self = CE_PAGE (g_object_new (page_type,
Packit Service d328f3
	                              CE_PAGE_CONNECTION, connection,
Packit Service d328f3
	                              CE_PAGE_PARENT_WINDOW, parent_window,
Packit Service d328f3
	                              NULL));
Packit Service d328f3
	self->title = g_strdup (title);
Packit Service d328f3
	self->client = client;
Packit Service d328f3
	self->editor = editor;
Packit Service d328f3
Packit Service d328f3
	if (ui_resource) {
Packit Service d328f3
		if (!gtk_builder_add_from_resource (self->builder, ui_resource, &error)) {
Packit Service d328f3
			g_warning ("Couldn't load builder resource: %s", error->message);
Packit Service d328f3
			g_error_free (error);
Packit Service d328f3
			g_object_unref (self);
Packit Service d328f3
			return NULL;
Packit Service d328f3
		}
Packit Service d328f3
Packit Service d328f3
		self->page = GTK_WIDGET (gtk_builder_get_object (self->builder, widget_name));
Packit Service d328f3
		if (!self->page) {
Packit Service d328f3
			g_warning ("Couldn't load page widget '%s' from %s", widget_name, ui_resource);
Packit Service d328f3
			g_object_unref (self);
Packit Service d328f3
			return NULL;
Packit Service d328f3
		}
Packit Service d328f3
		g_object_ref_sink (self->page);
Packit Service d328f3
	}
Packit Service d328f3
	return self;
Packit Service d328f3
}
Packit Service d328f3