page-wifi.c 20.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* NetworkManager Connection editor -- Connection editor for NetworkManager
 *
 * Dan Williams <dcbw@redhat.com>
 *
 * 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.
 *
16 17 18
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
 *
Dan Winship's avatar
Dan Winship committed
20
 * Copyright 2008 - 2014 Red Hat, Inc.
21 22
 */

23 24
#include "config.h"

25 26 27 28 29 30
#include <string.h>
#include <math.h>

#include <gtk/gtk.h>
#include <glib/gi18n.h>

31
#include "page-wifi.h"
32

33
G_DEFINE_TYPE (CEPageWifi, ce_page_wifi, CE_TYPE_PAGE)
34

35
#define CE_PAGE_WIFI_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CE_TYPE_PAGE_WIFI, CEPageWifiPrivate))
36 37 38 39 40

typedef struct {
	NMSettingWireless *setting;

	GtkEntry *ssid;
41
	GtkComboBoxText *bssid;
42 43
	GtkComboBoxText *device_combo; /* Device identification (ifname and/or MAC) */
	GtkEntry *cloned_mac;          /* Cloned MAC - used for MAC spoofing */
44 45 46 47 48 49 50
	GtkComboBox *mode;
	GtkComboBox *band;
	GtkSpinButton *channel;
	GtkSpinButton *rate;
	GtkSpinButton *tx_power;
	GtkSpinButton *mtu;

51 52
	GtkSizeGroup *group;

53
	int last_channel;
54
} CEPageWifiPrivate;
55 56

static void
57
wifi_private_init (CEPageWifi *self)
58
{
59
	CEPageWifiPrivate *priv = CE_PAGE_WIFI_GET_PRIVATE (self);
60
	GtkBuilder *builder;
61
	GtkWidget *widget;
62
	GtkWidget *vbox;
63
	GtkLabel *label;
64

65
	builder = CE_PAGE (self)->builder;
66

67 68
	priv->group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);

69 70 71 72 73
	priv->ssid     = GTK_ENTRY (gtk_builder_get_object (builder, "wifi_ssid"));
	priv->cloned_mac = GTK_ENTRY (gtk_builder_get_object (builder, "wifi_cloned_mac"));
	priv->mode     = GTK_COMBO_BOX (gtk_builder_get_object (builder, "wifi_mode"));
	priv->band     = GTK_COMBO_BOX (gtk_builder_get_object (builder, "wifi_band"));
	priv->channel  = GTK_SPIN_BUTTON (gtk_builder_get_object (builder, "wifi_channel"));
74

75 76 77 78 79 80
	/* BSSID */
	priv->bssid = GTK_COMBO_BOX_TEXT (gtk_combo_box_text_new_with_entry ());
	gtk_combo_box_set_entry_text_column (GTK_COMBO_BOX (priv->bssid), 0);
	gtk_widget_set_tooltip_text (GTK_WIDGET (priv->bssid),
	                             _("This option locks this connection to the Wi-Fi access point (AP) specified by the BSSID entered here.  Example: 00:11:22:33:44:55"));

81 82 83
	vbox = GTK_WIDGET (gtk_builder_get_object (builder, "wifi_bssid_vbox"));
	gtk_container_add (GTK_CONTAINER (vbox), GTK_WIDGET (priv->bssid));
	gtk_widget_set_halign (GTK_WIDGET (priv->bssid), GTK_ALIGN_FILL);
84 85 86
	gtk_widget_show_all (GTK_WIDGET (priv->bssid));

	/* Device MAC */
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
	priv->device_combo = GTK_COMBO_BOX_TEXT (gtk_combo_box_text_new_with_entry ());
	gtk_combo_box_set_entry_text_column (GTK_COMBO_BOX (priv->device_combo), 0);
	gtk_widget_set_tooltip_text (GTK_WIDGET (priv->device_combo),
	                             _("This option locks this connection to the network device specified "
	                               "either by its interface name or permanent MAC or both. Examples: "
	                               "\"wlan0\", \"3C:97:0E:42:1A:19\", \"wlan0 (3C:97:0E:42:1A:19)\""));

	vbox = GTK_WIDGET (gtk_builder_get_object (builder, "wifi_device_vbox"));
	gtk_container_add (GTK_CONTAINER (vbox), GTK_WIDGET (priv->device_combo));
	gtk_widget_set_halign (GTK_WIDGET (priv->device_combo), GTK_ALIGN_FILL);
	gtk_widget_show_all (GTK_WIDGET (priv->device_combo));

	/* Set mnemonic widget for Device label */
	label = GTK_LABEL (gtk_builder_get_object (builder, "wifi_device_label"));
	gtk_label_set_mnemonic_widget (label, GTK_WIDGET (priv->device_combo));
102

103
	priv->rate     = GTK_SPIN_BUTTON (gtk_builder_get_object (builder, "wifi_rate"));
104
	widget = GTK_WIDGET (gtk_builder_get_object (builder, "rate_units"));
105 106
	gtk_size_group_add_widget (priv->group, widget);

107
	priv->tx_power = GTK_SPIN_BUTTON (gtk_builder_get_object (builder, "wifi_tx_power"));
108
	widget = GTK_WIDGET (gtk_builder_get_object (builder, "tx_power_units"));
109 110
	gtk_size_group_add_widget (priv->group, widget);

111
	priv->mtu      = GTK_SPIN_BUTTON (gtk_builder_get_object (builder, "wifi_mtu"));
112
	widget = GTK_WIDGET (gtk_builder_get_object (builder, "mtu_units"));
113
	gtk_size_group_add_widget (priv->group, widget);
114 115
}

116
static gboolean
117
band_helper (CEPageWifi *self, gboolean *aband, gboolean *gband)
118
{
119
	CEPageWifiPrivate *priv = CE_PAGE_WIFI_GET_PRIVATE (self);
120

121
	switch (gtk_combo_box_get_active (priv->band)) {
122 123 124 125 126 127 128 129 130 131 132 133 134 135
	case 1: /* A */
		*gband = FALSE;
		return TRUE;
	case 2: /* B/G */
		*aband = FALSE;
		return TRUE;
	default:
		return FALSE;
	}
}

static gint
channel_spin_input_cb (GtkSpinButton *spin, gdouble *new_val, gpointer user_data)
{
136
	CEPageWifi *self = CE_PAGE_WIFI (user_data);
137 138 139 140 141
	gdouble channel;
	guint32 int_channel = 0;
	gboolean aband = TRUE;
	gboolean gband = TRUE;

142
	if (!band_helper (self, &aband, &gband))
143 144 145 146 147 148 149 150
		return GTK_INPUT_ERROR;

	channel = g_strtod (gtk_entry_get_text (GTK_ENTRY (spin)), NULL);
	if (channel - floor (channel) < ceil (channel) - channel)
		int_channel = floor (channel);
	else
		int_channel = ceil (channel);

151
	if (nm_utils_wifi_channel_to_freq (int_channel, aband ? "a" : "bg") == -1)
152 153 154
		return GTK_INPUT_ERROR;

	*new_val = channel;
155
	return 1;
156 157 158 159 160
}

static gint
channel_spin_output_cb (GtkSpinButton *spin, gpointer user_data)
{
161 162
	CEPageWifi *self = CE_PAGE_WIFI (user_data);
	CEPageWifiPrivate *priv = CE_PAGE_WIFI_GET_PRIVATE (self);
163 164 165 166 167 168
	int channel;
	gchar *buf = NULL;
	guint32 freq;
	gboolean aband = TRUE;
	gboolean gband = TRUE;

169
	if (!band_helper (self, &aband, &gband))
170 171 172 173 174 175
		buf = g_strdup (_("default"));
	else {
		channel = gtk_spin_button_get_value_as_int (spin);
		if (channel == 0)
			buf = g_strdup (_("default"));
		else {
176 177
			int direction = 0;
			freq = nm_utils_wifi_channel_to_freq (channel, aband ? "a" : "bg");
178
			if (freq == -1) {
179
				if (priv->last_channel < channel)
180
					direction = 1;
181
				else if (priv->last_channel > channel)
182
					direction = -1;
183 184 185
				channel = nm_utils_wifi_find_next_channel (channel, direction, aband ? "a" : "bg");
				gtk_spin_button_set_value (spin, channel);
				freq = nm_utils_wifi_channel_to_freq (channel, aband ? "a" : "bg");
186 187 188 189 190
				if (freq == -1) {
					g_warning ("%s: invalid channel %d!", __func__, channel);
					gtk_spin_button_set_value (spin, 0);
					goto out;
				}
191

192
			}
193 194 195 196 197 198 199
			/* Set spin button to zero to go to "default" from the lowest channel */
			if (direction == -1 && priv->last_channel == channel) {
				buf = g_strdup_printf (_("default"));
				gtk_spin_button_set_value (spin, 0);
				channel = 0;
			} else
				buf = g_strdup_printf (_("%u (%u MHz)"), channel, freq);
200
		}
201
		priv->last_channel = channel;
202 203 204 205 206 207 208
	}

	if (strcmp (buf, gtk_entry_get_text (GTK_ENTRY (spin))))
		gtk_entry_set_text (GTK_ENTRY (spin), buf);

out:
	g_free (buf);
209
	return 1;
210 211 212 213 214
}

static void
band_value_changed_cb (GtkComboBox *box, gpointer user_data)
{
215 216
	CEPageWifi *self = CE_PAGE_WIFI (user_data);
	CEPageWifiPrivate *priv = CE_PAGE_WIFI_GET_PRIVATE (self);
217 218 219 220 221 222 223 224 225 226 227 228 229 230
	gboolean sensitive;

	priv->last_channel = 0;
	gtk_spin_button_set_value (priv->channel, 0);
 
 	switch (gtk_combo_box_get_active (GTK_COMBO_BOX (box))) {
 	case 1: /* A */
 	case 2: /* B/G */
		sensitive = TRUE;
 		break;
 	default:
		sensitive = FALSE;
 		break;
 	}
231

232
	gtk_widget_set_sensitive (GTK_WIDGET (priv->channel), sensitive);
233

234
	ce_page_changed (CE_PAGE (self));
235 236
}

237 238 239 240
static void
mode_combo_changed_cb (GtkComboBox *combo,
                       gpointer user_data)
{
241 242
	CEPageWifi *self = CE_PAGE_WIFI (user_data);
	CEPageWifiPrivate *priv = CE_PAGE_WIFI_GET_PRIVATE (self);
243
	CEPage *parent = CE_PAGE (self);
244 245
	GtkWidget *widget_band_label, *widget_chan_label, *widget_bssid_label;
	gboolean adhoc;
246 247 248

 	switch (gtk_combo_box_get_active (GTK_COMBO_BOX (combo))) {
 	case 1: /* adhoc */
249
		adhoc = TRUE;
250 251
 		break;
 	default: /* infrastructure */
252
		adhoc = FALSE;
253 254 255
 		break;
 	}

256 257 258 259 260 261 262
	widget_band_label = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wifi_band_label"));
	widget_chan_label = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wifi_channel_label"));
	widget_bssid_label = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wifi_bssid_label"));

	if (adhoc) {
		/* For Ad-Hoc show Band and Channel */
		gtk_widget_show (widget_band_label);
263
		gtk_widget_show (GTK_WIDGET (priv->band));
264
		gtk_widget_show (widget_chan_label);
265
		gtk_widget_show (GTK_WIDGET (priv->channel));
266 267 268 269 270 271 272

		/* and hide BSSID
		 * BSSID is random and is created by kernel for Ad-Hoc networks
		 * http://lxr.linux.no/linux+v3.7.6/net/mac80211/ibss.c#L685
		 */
		gtk_widget_hide (widget_bssid_label);
		gtk_widget_hide (GTK_WIDGET (priv->bssid));
273
	} else {
274 275
		/* Do opposite for Infrastructure mode */
		gtk_widget_hide (widget_band_label);
276
		gtk_widget_hide (GTK_WIDGET (priv->band));
277
		gtk_widget_hide (widget_chan_label);
278
		gtk_widget_hide (GTK_WIDGET (priv->channel));
279 280 281

		gtk_widget_show (widget_bssid_label);
		gtk_widget_show (GTK_WIDGET (priv->bssid));
282 283
	}

284 285 286 287 288 289
	gtk_widget_set_sensitive (widget_band_label, adhoc);
	gtk_widget_set_sensitive (GTK_WIDGET (priv->band), adhoc);
	gtk_widget_set_sensitive (widget_chan_label, adhoc);
	gtk_widget_set_sensitive (GTK_WIDGET (priv->channel), adhoc);
	gtk_widget_set_sensitive (widget_bssid_label, !adhoc);
	gtk_widget_set_sensitive (GTK_WIDGET (priv->bssid), !adhoc);
290 291 292 293

	ce_page_changed (CE_PAGE (self));
}

294
static void
295
populate_ui (CEPageWifi *self)
296
{
297
	CEPageWifiPrivate *priv = CE_PAGE_WIFI_GET_PRIVATE (self);
298
	NMSettingWireless *setting = priv->setting;
Dan Winship's avatar
Dan Winship committed
299 300 301
	GBytes *ssid;
	const char *mode;
	const char *band;
302
	int band_idx = 0;
303 304 305
	int rate_def;
	int tx_power_def;
	int mtu_def;
306
	char *utf8_ssid;
307
	const char *s_ifname, *s_mac, *s_bssid;
308 309 310
	GPtrArray *bssid_array;
	char **bssid_list;
	guint32 idx;
311

312 313
	rate_def = ce_get_property_default (NM_SETTING (setting), NM_SETTING_WIRELESS_RATE);
	g_signal_connect (priv->rate, "output",
314
	                  G_CALLBACK (ce_spin_output_with_automatic),
315
	                  GINT_TO_POINTER (rate_def));
316
	g_signal_connect_swapped (priv->rate, "value-changed", G_CALLBACK (ce_page_changed), self);
317

318 319
	tx_power_def = ce_get_property_default (NM_SETTING (setting), NM_SETTING_WIRELESS_TX_POWER);
	g_signal_connect (priv->tx_power, "output",
320
	                  G_CALLBACK (ce_spin_output_with_automatic),
321
	                  GINT_TO_POINTER (tx_power_def));
322
	g_signal_connect_swapped (priv->tx_power, "value-changed", G_CALLBACK (ce_page_changed), self);
323

324 325
	mtu_def = ce_get_property_default (NM_SETTING (setting), NM_SETTING_WIRELESS_MTU);
	g_signal_connect (priv->mtu, "output",
326
	                  G_CALLBACK (ce_spin_output_with_automatic),
327
	                  GINT_TO_POINTER (mtu_def));
328
	g_signal_connect_swapped (priv->mtu, "value-changed", G_CALLBACK (ce_page_changed), self);
329

Dan Winship's avatar
Dan Winship committed
330 331 332
	ssid = nm_setting_wireless_get_ssid (setting);
	mode = nm_setting_wireless_get_mode (setting);
	band = nm_setting_wireless_get_band (setting);
333 334

	if (ssid)
Dan Winship's avatar
Dan Winship committed
335 336
		utf8_ssid = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL),
		                                   g_bytes_get_size (ssid));
337 338
	else
		utf8_ssid = g_strdup ("");
339
	gtk_entry_set_text (priv->ssid, utf8_ssid);
340
	g_signal_connect_swapped (priv->ssid, "changed", G_CALLBACK (ce_page_changed), self);
341
	g_free (utf8_ssid);
342

343 344
	/* Default to Infrastructure */
	gtk_combo_box_set_active (priv->mode, 0);
345
	if (mode && !strcmp (mode, "adhoc"))
346
		gtk_combo_box_set_active (priv->mode, 1);
347 348
	mode_combo_changed_cb (priv->mode, self);
	g_signal_connect (priv->mode, "changed", G_CALLBACK (mode_combo_changed_cb), self);
349

350 351
	g_signal_connect (priv->channel, "output",
	                  G_CALLBACK (channel_spin_output_cb),
352
	                  self);
353 354
	g_signal_connect (priv->channel, "input",
	                  G_CALLBACK (channel_spin_input_cb),
355
	                  self);
356

357
	gtk_widget_set_sensitive (GTK_WIDGET (priv->channel), FALSE);
358 359
	if (band) {
		if (!strcmp (band ? band : "", "a")) {
360
			band_idx = 1;
361
			gtk_widget_set_sensitive (GTK_WIDGET (priv->channel), TRUE);
362
		} else if (!strcmp (band ? band : "", "bg")) {
363
			band_idx = 2;
364
			gtk_widget_set_sensitive (GTK_WIDGET (priv->channel), TRUE);
365 366
		}
	}
367 368 369 370

	gtk_combo_box_set_active (priv->band, band_idx);
	g_signal_connect (priv->band, "changed",
	                  G_CALLBACK (band_value_changed_cb),
371
	                  self);
372 373 374

	/* Update the channel _after_ the band has been set so that it gets
	 * the right values */
375 376
	priv->last_channel = nm_setting_wireless_get_channel (setting);
	gtk_spin_button_set_value (priv->channel, (gdouble) priv->last_channel);
377
	g_signal_connect_swapped (priv->channel, "value-changed", G_CALLBACK (ce_page_changed), self);
378

379
	/* BSSID */
380 381 382 383 384
	bssid_array = g_ptr_array_new ();
	for (idx = 0; idx < nm_setting_wireless_get_num_seen_bssids (setting); idx++)
		g_ptr_array_add (bssid_array, g_strdup (nm_setting_wireless_get_seen_bssid (setting, idx)));
	g_ptr_array_add (bssid_array, NULL);
	bssid_list = (char **) g_ptr_array_free (bssid_array, FALSE);
385
	s_bssid = nm_setting_wireless_get_bssid (setting);
386
	ce_page_setup_mac_combo (CE_PAGE (self), GTK_COMBO_BOX (priv->bssid),
387
	                         s_bssid, bssid_list);
388
	g_strfreev (bssid_list);
389
	g_signal_connect_swapped (priv->bssid, "changed", G_CALLBACK (ce_page_changed), self);
390

391
	/* Device MAC address */
392 393 394 395 396 397
        s_ifname = nm_connection_get_interface_name (CE_PAGE (self)->connection);
	s_mac = nm_setting_wireless_get_mac_address (setting);
	ce_page_setup_device_combo (CE_PAGE (self), GTK_COMBO_BOX (priv->device_combo),
	                            NM_TYPE_DEVICE_WIFI, s_ifname,
	                            s_mac, NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS, TRUE);
	g_signal_connect_swapped (priv->device_combo, "changed", G_CALLBACK (ce_page_changed), self);
398 399

	/* Cloned MAC address */
400 401 402
	s_mac = nm_setting_wireless_get_cloned_mac_address (setting);
	if (s_mac)
		gtk_entry_set_text (priv->cloned_mac, s_mac);
403
	g_signal_connect_swapped (priv->cloned_mac, "changed", G_CALLBACK (ce_page_changed), self);
404

405 406 407
	gtk_spin_button_set_value (priv->rate, (gdouble) nm_setting_wireless_get_rate (setting));
	gtk_spin_button_set_value (priv->tx_power, (gdouble) nm_setting_wireless_get_tx_power (setting));
	gtk_spin_button_set_value (priv->mtu, (gdouble) nm_setting_wireless_get_mtu (setting));
408 409
}

410
static void
411
finish_setup (CEPageWifi *self, gpointer unused, GError *error, gpointer user_data)
412 413 414 415 416 417 418 419 420
{
	CEPage *parent = CE_PAGE (self);
	GtkWidget *widget;

	if (error)
		return;

	populate_ui (self);

421
	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wifi_tx_power_label"));
422
	gtk_widget_hide (widget);
423
	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wifi_tx_power_hbox"));
424 425
	gtk_widget_hide (widget);

426
	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wifi_rate_label"));
427
	gtk_widget_hide (widget);
428
	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wifi_rate_hbox"));
429 430 431 432
	gtk_widget_hide (widget);
}

CEPage *
433 434 435 436 437
ce_page_wifi_new (NMConnection *connection,
                  GtkWindow *parent_window,
                  NMClient *client,
                  const char **out_secrets_setting_name,
                  GError **error)
438
{
439 440
	CEPageWifi *self;
	CEPageWifiPrivate *priv;
441 442 443

	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);

444 445 446 447 448 449 450
	self = CE_PAGE_WIFI (ce_page_new (CE_TYPE_PAGE_WIFI,
	                                  connection,
	                                  parent_window,
	                                  client,
	                                  UIDIR "/ce-page-wifi.ui",
	                                  "WifiPage",
	                                  _("Wi-Fi")));
451
	if (!self) {
452
		g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("Could not load Wi-Fi user interface."));
453 454 455
		return NULL;
	}

456 457
	wifi_private_init (self);
	priv = CE_PAGE_WIFI_GET_PRIVATE (self);
458

459
	priv->setting = nm_connection_get_setting_wireless (connection);
460
	if (!priv->setting) {
461
		priv->setting = NM_SETTING_WIRELESS (nm_setting_wireless_new ());
462 463
		nm_connection_add_setting (connection, NM_SETTING (priv->setting));
	}
464

465
	g_signal_connect (self, "initialized", G_CALLBACK (finish_setup), NULL);
466

467
	return CE_PAGE (self);
468 469
}

Dan Winship's avatar
Dan Winship committed
470
GBytes *
471
ce_page_wifi_get_ssid (CEPageWifi *self)
472
{
473
	CEPageWifiPrivate *priv;
474
	const char *txt_ssid;
Dan Winship's avatar
Dan Winship committed
475
	GBytes *ssid;
476

477
	g_return_val_if_fail (CE_IS_PAGE_WIFI (self), NULL);
478

479
	priv = CE_PAGE_WIFI_GET_PRIVATE (self);
480
	txt_ssid = gtk_entry_get_text (priv->ssid);
481 482 483
	if (!txt_ssid || !strlen (txt_ssid))
		return NULL;

Dan Winship's avatar
Dan Winship committed
484
	ssid = g_bytes_new (txt_ssid, strlen (txt_ssid));
485

486
	return ssid;
487 488
}

489
static void
490
ui_to_setting (CEPageWifi *self)
491
{
492
	CEPageWifiPrivate *priv = CE_PAGE_WIFI_GET_PRIVATE (self);
493
	NMSettingConnection *s_con;
Dan Winship's avatar
Dan Winship committed
494
	GBytes *ssid;
495 496
	const char *bssid = NULL;
	char *ifname = NULL;
Dan Winship's avatar
Dan Winship committed
497
	char *device_mac = NULL;
498
	const char *cloned_mac;
499 500
	const char *mode;
	const char *band;
501
	GtkWidget *entry;
502

503 504 505
	s_con = nm_connection_get_setting_connection (CE_PAGE (self)->connection);
	g_return_if_fail (s_con != NULL);

506
	ssid = ce_page_wifi_get_ssid (self);
507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525

	if (gtk_combo_box_get_active (priv->mode) == 1)
		mode = "adhoc";
	else
		mode = "infrastructure";

	switch (gtk_combo_box_get_active (priv->band)) {
	case 1:
		band = "a";
		break;
	case 2:
		band = "bg";
		break;
	case 0:
	default:
		band = NULL;
		break;
	}

526
	entry = gtk_bin_get_child (GTK_BIN (priv->bssid));
527 528
	/* BSSID is only valid for infrastructure not for adhoc */
	if (entry && mode && strcmp (mode, "adhoc") != 0)
529 530
		bssid = gtk_entry_get_text (GTK_ENTRY (entry));
	entry = gtk_bin_get_child (GTK_BIN (priv->device_combo));
531
	if (entry)
532
		ce_page_device_entry_get (GTK_ENTRY (entry), ARPHRD_ETHER, &ifname, &device_mac, NULL, NULL);
533
	cloned_mac = gtk_entry_get_text (priv->cloned_mac);
534

535 536 537
	g_object_set (s_con,
	              NM_SETTING_CONNECTION_INTERFACE_NAME, ifname,
	              NULL);
538
	g_object_set (priv->setting,
Jiří Klimeš's avatar
Jiří Klimeš committed
539
	              NM_SETTING_WIRELESS_SSID, ssid,
540
	              NM_SETTING_WIRELESS_BSSID, bssid && *bssid ? bssid : NULL,
Jiří Klimeš's avatar
Jiří Klimeš committed
541
	              NM_SETTING_WIRELESS_MAC_ADDRESS, device_mac,
542
	              NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, cloned_mac && *cloned_mac ? cloned_mac : NULL,
Jiří Klimeš's avatar
Jiří Klimeš committed
543 544 545 546 547 548 549
	              NM_SETTING_WIRELESS_MODE, mode,
	              NM_SETTING_WIRELESS_BAND, band,
	              NM_SETTING_WIRELESS_CHANNEL, gtk_spin_button_get_value_as_int (priv->channel),
	              NM_SETTING_WIRELESS_RATE, gtk_spin_button_get_value_as_int (priv->rate),
	              NM_SETTING_WIRELESS_TX_POWER, gtk_spin_button_get_value_as_int (priv->tx_power),
	              NM_SETTING_WIRELESS_MTU, gtk_spin_button_get_value_as_int (priv->mtu),
	              NULL);
550

Dan Winship's avatar
Dan Winship committed
551
	g_bytes_unref (ssid);
552
	g_free (ifname);
Dan Winship's avatar
Dan Winship committed
553
	g_free (device_mac);
554 555 556
}

static gboolean
557
ce_page_validate_v (CEPage *page, NMConnection *connection, GError **error)
558
{
559 560
	CEPageWifi *self = CE_PAGE_WIFI (page);
	CEPageWifiPrivate *priv = CE_PAGE_WIFI_GET_PRIVATE (self);
561
	gboolean success;
562
	GtkWidget *entry;
563

564 565
	entry = gtk_bin_get_child (GTK_BIN (priv->bssid));
	if (entry) {
566
		if (!ce_page_mac_entry_valid (GTK_ENTRY (entry), ARPHRD_ETHER, _("bssid"), error))
567 568
			return FALSE;
	}
569

570
	entry = gtk_bin_get_child (GTK_BIN (priv->device_combo));
571
	if (entry) {
572
		if (!ce_page_device_entry_get (GTK_ENTRY (entry), ARPHRD_ETHER, NULL, NULL, _("Wi-Fi device"), error))
573 574
			return FALSE;
	}
575

576
	if (!ce_page_mac_entry_valid (priv->cloned_mac, ARPHRD_ETHER, _("cloned MAC"), error))
577
		return FALSE;
578 579 580

	ui_to_setting (self);

581
	success = nm_setting_verify (NM_SETTING (priv->setting), NULL, error);
582 583 584 585

	return success;
}

586
static void
587
ce_page_wifi_init (CEPageWifi *self)
588 589
{
}
590

591
static void
592
ce_page_wifi_class_init (CEPageWifiClass *wifi_class)
593
{
594 595
	GObjectClass *object_class = G_OBJECT_CLASS (wifi_class);
	CEPageClass *parent_class = CE_PAGE_CLASS (wifi_class);
596

597
	g_type_class_add_private (object_class, sizeof (CEPageWifiPrivate));
598

599
	/* virtual methods */
600
	parent_class->ce_page_validate_v = ce_page_validate_v;
601
}
602 603 604 605


void
wifi_connection_new (GtkWindow *parent,
606
                     const char *detail,
Dan Winship's avatar
Dan Winship committed
607
                     NMClient *client,
608 609 610 611 612 613
                     PageNewConnectionResultFunc result_func,
                     gpointer user_data)
{
	NMConnection *connection;
	NMSetting *s_wifi;

614
	connection = ce_page_new_connection (_("Wi-Fi connection %d"),
615 616
	                                     NM_SETTING_WIRELESS_SETTING_NAME,
	                                     TRUE,
Dan Winship's avatar
Dan Winship committed
617
	                                     client,
618 619 620 621 622 623 624 625 626
	                                     user_data);
	s_wifi = nm_setting_wireless_new ();
	g_object_set (s_wifi, NM_SETTING_WIRELESS_MODE, "infrastructure", NULL);
	nm_connection_add_setting (connection, s_wifi);

	(*result_func) (connection, FALSE, NULL, user_data);
}