1
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2
/* NetworkManager Connection editor -- Connection editor for NetworkManager
4
* Dan Williams <dcbw@redhat.com>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License along
17
* with this program; if not, write to the Free Software Foundation, Inc.,
18
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
* (C) Copyright 2008 - 2012 Red Hat, Inc.
29
#include <glib/gi18n.h>
31
#include <nm-setting-connection.h>
32
#include <nm-setting-wireless.h>
33
#include <nm-device-wifi.h>
36
#include "page-wifi.h"
38
G_DEFINE_TYPE (CEPageWifi, ce_page_wifi, CE_TYPE_PAGE)
40
#define CE_PAGE_WIFI_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CE_TYPE_PAGE_WIFI, CEPageWifiPrivate))
43
NMSettingWireless *setting;
46
#if GTK_CHECK_VERSION (2,24,0)
47
GtkComboBoxText *bssid;
49
GtkComboBoxEntry *bssid;
51
#if GTK_CHECK_VERSION (2,24,0)
52
GtkComboBoxText *device_mac; /* Permanent MAC of the device */
54
GtkComboBoxEntry *device_mac;
56
GtkEntry *cloned_mac; /* Cloned MAC - used for MAC spoofing */
59
GtkSpinButton *channel;
61
GtkSpinButton *tx_power;
71
wifi_private_init (CEPageWifi *self)
73
CEPageWifiPrivate *priv = CE_PAGE_WIFI_GET_PRIVATE (self);
79
builder = CE_PAGE (self)->builder;
81
priv->group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
83
priv->ssid = GTK_ENTRY (GTK_WIDGET (gtk_builder_get_object (builder, "wifi_ssid")));
84
priv->cloned_mac = GTK_ENTRY (GTK_WIDGET (gtk_builder_get_object (builder, "wifi_cloned_mac")));
85
priv->mode = GTK_COMBO_BOX (GTK_WIDGET (gtk_builder_get_object (builder, "wifi_mode")));
86
priv->band = GTK_COMBO_BOX (GTK_WIDGET (gtk_builder_get_object (builder, "wifi_band")));
87
priv->channel = GTK_SPIN_BUTTON (GTK_WIDGET (gtk_builder_get_object (builder, "wifi_channel")));
90
#if GTK_CHECK_VERSION(2,24,0)
91
priv->bssid = GTK_COMBO_BOX_TEXT (gtk_combo_box_text_new_with_entry ());
92
gtk_combo_box_set_entry_text_column (GTK_COMBO_BOX (priv->bssid), 0);
94
priv->bssid = GTK_COMBO_BOX_ENTRY (gtk_combo_box_entry_new_text ());
95
gtk_combo_box_entry_set_text_column (GTK_COMBO_BOX_ENTRY (priv->bssid), 0);
97
gtk_widget_set_tooltip_text (GTK_WIDGET (priv->bssid),
98
_("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"));
100
align = GTK_WIDGET (gtk_builder_get_object (builder, "wifi_bssid_alignment"));
101
gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET (priv->bssid));
102
gtk_widget_show_all (GTK_WIDGET (priv->bssid));
105
#if GTK_CHECK_VERSION(2,24,0)
106
priv->device_mac = GTK_COMBO_BOX_TEXT (gtk_combo_box_text_new_with_entry ());
107
gtk_combo_box_set_entry_text_column (GTK_COMBO_BOX (priv->device_mac), 0);
109
priv->device_mac = GTK_COMBO_BOX_ENTRY (gtk_combo_box_entry_new_text ());
110
gtk_combo_box_entry_set_text_column (GTK_COMBO_BOX_ENTRY (priv->device_mac), 0);
112
gtk_widget_set_tooltip_text (GTK_WIDGET (priv->device_mac),
113
_("This option locks this connection to the network device specified by its permanent MAC address entered here. Example: 00:11:22:33:44:55"));
115
align = GTK_WIDGET (gtk_builder_get_object (builder, "wifi_device_mac_alignment"));
116
gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET (priv->device_mac));
117
gtk_widget_show_all (GTK_WIDGET (priv->device_mac));
119
/* Set mnemonic widget for device MAC label */
120
label = GTK_LABEL (GTK_WIDGET (gtk_builder_get_object (builder, "wifi_device_mac_label")));
121
gtk_label_set_mnemonic_widget (label, GTK_WIDGET (priv->device_mac));
123
priv->rate = GTK_SPIN_BUTTON (GTK_WIDGET (gtk_builder_get_object (builder, "wifi_rate")));
124
widget = GTK_WIDGET (gtk_builder_get_object (builder, "rate_units"));
125
gtk_size_group_add_widget (priv->group, widget);
127
priv->tx_power = GTK_SPIN_BUTTON (GTK_WIDGET (gtk_builder_get_object (builder, "wifi_tx_power")));
128
widget = GTK_WIDGET (gtk_builder_get_object (builder, "tx_power_units"));
129
gtk_size_group_add_widget (priv->group, widget);
131
priv->mtu = GTK_SPIN_BUTTON (GTK_WIDGET (gtk_builder_get_object (builder, "wifi_mtu")));
132
widget = GTK_WIDGET (gtk_builder_get_object (builder, "mtu_units"));
133
gtk_size_group_add_widget (priv->group, widget);
137
band_helper (CEPageWifi *self, gboolean *aband, gboolean *gband)
139
CEPageWifiPrivate *priv = CE_PAGE_WIFI_GET_PRIVATE (self);
141
switch (gtk_combo_box_get_active (priv->band)) {
154
channel_spin_input_cb (GtkSpinButton *spin, gdouble *new_val, gpointer user_data)
156
CEPageWifi *self = CE_PAGE_WIFI (user_data);
158
guint32 int_channel = 0;
159
gboolean aband = TRUE;
160
gboolean gband = TRUE;
162
if (!band_helper (self, &aband, &gband))
163
return GTK_INPUT_ERROR;
165
channel = g_strtod (gtk_entry_get_text (GTK_ENTRY (spin)), NULL);
166
if (channel - floor (channel) < ceil (channel) - channel)
167
int_channel = floor (channel);
169
int_channel = ceil (channel);
171
if (nm_utils_wifi_channel_to_freq (int_channel, aband ? "a" : "bg") == -1)
172
return GTK_INPUT_ERROR;
179
channel_spin_output_cb (GtkSpinButton *spin, gpointer user_data)
181
CEPageWifi *self = CE_PAGE_WIFI (user_data);
182
CEPageWifiPrivate *priv = CE_PAGE_WIFI_GET_PRIVATE (self);
186
gboolean aband = TRUE;
187
gboolean gband = TRUE;
189
if (!band_helper (self, &aband, &gband))
190
buf = g_strdup (_("default"));
192
channel = gtk_spin_button_get_value_as_int (spin);
194
buf = g_strdup (_("default"));
197
freq = nm_utils_wifi_channel_to_freq (channel, aband ? "a" : "bg");
199
if (priv->last_channel < channel)
201
else if (priv->last_channel > channel)
203
channel = nm_utils_wifi_find_next_channel (channel, direction, aband ? "a" : "bg");
204
gtk_spin_button_set_value (spin, channel);
205
freq = nm_utils_wifi_channel_to_freq (channel, aband ? "a" : "bg");
207
g_warning ("%s: invalid channel %d!", __func__, channel);
208
gtk_spin_button_set_value (spin, 0);
213
/* Set spin button to zero to go to "default" from the lowest channel */
214
if (direction == -1 && priv->last_channel == channel) {
215
buf = g_strdup_printf (_("default"));
216
gtk_spin_button_set_value (spin, 0);
219
buf = g_strdup_printf (_("%u (%u MHz)"), channel, freq);
221
priv->last_channel = channel;
224
if (strcmp (buf, gtk_entry_get_text (GTK_ENTRY (spin))))
225
gtk_entry_set_text (GTK_ENTRY (spin), buf);
233
band_value_changed_cb (GtkComboBox *box, gpointer user_data)
235
CEPageWifi *self = CE_PAGE_WIFI (user_data);
236
CEPageWifiPrivate *priv = CE_PAGE_WIFI_GET_PRIVATE (self);
239
priv->last_channel = 0;
240
gtk_spin_button_set_value (priv->channel, 0);
242
switch (gtk_combo_box_get_active (GTK_COMBO_BOX (box))) {
252
gtk_widget_set_sensitive (GTK_WIDGET (priv->channel), sensitive);
254
ce_page_changed (CE_PAGE (self));
258
mode_combo_changed_cb (GtkComboBox *combo,
261
CEPageWifi *self = CE_PAGE_WIFI (user_data);
262
CEPageWifiPrivate *priv = CE_PAGE_WIFI_GET_PRIVATE (self);
263
CEPage *parent = CE_PAGE (self);
267
switch (gtk_combo_box_get_active (GTK_COMBO_BOX (combo))) {
271
default: /* infrastructure */
277
widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wifi_band_label"));
278
gtk_widget_show (widget);
279
gtk_widget_show (GTK_WIDGET (priv->band));
280
widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wifi_channel_label"));
281
gtk_widget_show (widget);
282
gtk_widget_show (GTK_WIDGET (priv->channel));
284
widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wifi_band_label"));
285
gtk_widget_hide (widget);
286
gtk_widget_hide (GTK_WIDGET (priv->band));
287
widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wifi_channel_label"));
288
gtk_widget_hide (widget);
289
gtk_widget_hide (GTK_WIDGET (priv->channel));
292
widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wifi_band_label"));
293
gtk_widget_set_sensitive (GTK_WIDGET (widget), show);
294
gtk_widget_set_sensitive (GTK_WIDGET (priv->band), show);
295
widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wifi_channel_label"));
296
gtk_widget_set_sensitive (GTK_WIDGET (widget), show);
297
gtk_widget_set_sensitive (GTK_WIDGET (priv->channel), show);
299
ce_page_changed (CE_PAGE (self));
303
populate_ui (CEPageWifi *self)
305
CEPageWifiPrivate *priv = CE_PAGE_WIFI_GET_PRIVATE (self);
306
NMSettingWireless *setting = priv->setting;
307
GByteArray *ssid = NULL;
316
const GByteArray *s_mac, *s_bssid;
317
char *s_mac_str, *s_bssid_str;
318
GPtrArray *bssid_array;
322
rate_def = ce_get_property_default (NM_SETTING (setting), NM_SETTING_WIRELESS_RATE);
323
g_signal_connect (priv->rate, "output",
324
G_CALLBACK (ce_spin_output_with_default),
325
GINT_TO_POINTER (rate_def));
326
g_signal_connect_swapped (priv->rate, "value-changed", G_CALLBACK (ce_page_changed), self);
328
tx_power_def = ce_get_property_default (NM_SETTING (setting), NM_SETTING_WIRELESS_TX_POWER);
329
g_signal_connect (priv->tx_power, "output",
330
G_CALLBACK (ce_spin_output_with_default),
331
GINT_TO_POINTER (tx_power_def));
332
g_signal_connect_swapped (priv->tx_power, "value-changed", G_CALLBACK (ce_page_changed), self);
334
mtu_def = ce_get_property_default (NM_SETTING (setting), NM_SETTING_WIRELESS_MTU);
335
g_signal_connect (priv->mtu, "output",
336
G_CALLBACK (ce_spin_output_with_default),
337
GINT_TO_POINTER (mtu_def));
338
g_signal_connect_swapped (priv->mtu, "value-changed", G_CALLBACK (ce_page_changed), self);
340
g_object_get (setting,
341
NM_SETTING_WIRELESS_SSID, &ssid,
342
NM_SETTING_WIRELESS_MODE, &mode,
343
NM_SETTING_WIRELESS_BAND, &band,
347
utf8_ssid = nm_utils_ssid_to_utf8 (ssid);
349
utf8_ssid = g_strdup ("");
350
gtk_entry_set_text (priv->ssid, utf8_ssid);
351
g_signal_connect_swapped (priv->ssid, "changed", G_CALLBACK (ce_page_changed), self);
353
g_byte_array_unref (ssid);
355
/* Default to Infrastructure */
356
gtk_combo_box_set_active (priv->mode, 0);
357
if (mode && !strcmp (mode, "adhoc"))
358
gtk_combo_box_set_active (priv->mode, 1);
359
mode_combo_changed_cb (priv->mode, self);
360
g_signal_connect (priv->mode, "changed", G_CALLBACK (mode_combo_changed_cb), self);
363
g_signal_connect (priv->channel, "output",
364
G_CALLBACK (channel_spin_output_cb),
366
g_signal_connect (priv->channel, "input",
367
G_CALLBACK (channel_spin_input_cb),
370
gtk_widget_set_sensitive (GTK_WIDGET (priv->channel), FALSE);
372
if (!strcmp (band ? band : "", "a")) {
374
gtk_widget_set_sensitive (GTK_WIDGET (priv->channel), TRUE);
375
} else if (!strcmp (band ? band : "", "bg")) {
377
gtk_widget_set_sensitive (GTK_WIDGET (priv->channel), TRUE);
382
gtk_combo_box_set_active (priv->band, band_idx);
383
g_signal_connect (priv->band, "changed",
384
G_CALLBACK (band_value_changed_cb),
387
/* Update the channel _after_ the band has been set so that it gets
388
* the right values */
389
priv->last_channel = nm_setting_wireless_get_channel (setting);
390
gtk_spin_button_set_value (priv->channel, (gdouble) priv->last_channel);
391
g_signal_connect_swapped (priv->channel, "value-changed", G_CALLBACK (ce_page_changed), self);
394
bssid_array = g_ptr_array_new ();
395
for (idx = 0; idx < nm_setting_wireless_get_num_seen_bssids (setting); idx++)
396
g_ptr_array_add (bssid_array, g_strdup (nm_setting_wireless_get_seen_bssid (setting, idx)));
397
g_ptr_array_add (bssid_array, NULL);
398
bssid_list = (char **) g_ptr_array_free (bssid_array, FALSE);
399
s_bssid = nm_setting_wireless_get_bssid (setting);
400
s_bssid_str = s_bssid ? nm_utils_hwaddr_ntoa (s_bssid->data, ARPHRD_ETHER) : NULL;
401
ce_page_setup_mac_combo (CE_PAGE (self), GTK_COMBO_BOX (priv->bssid),
402
s_bssid_str, bssid_list);
403
g_free (s_bssid_str);
404
g_strfreev (bssid_list);
405
g_signal_connect_swapped (priv->bssid, "changed", G_CALLBACK (ce_page_changed), self);
407
/* Device MAC address */
408
mac_list = ce_page_get_mac_list (CE_PAGE (self), NM_TYPE_DEVICE_WIFI,
409
NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS);
410
s_mac = nm_setting_wireless_get_mac_address (setting);
411
s_mac_str = s_mac ? nm_utils_hwaddr_ntoa (s_mac->data, ARPHRD_ETHER) : NULL;
412
ce_page_setup_mac_combo (CE_PAGE (self), GTK_COMBO_BOX (priv->device_mac),
413
s_mac_str, mac_list);
415
g_strfreev (mac_list);
416
g_signal_connect_swapped (priv->device_mac, "changed", G_CALLBACK (ce_page_changed), self);
418
/* Cloned MAC address */
419
ce_page_mac_to_entry (nm_setting_wireless_get_cloned_mac_address (setting),
420
ARPHRD_ETHER, priv->cloned_mac);
421
g_signal_connect_swapped (priv->cloned_mac, "changed", G_CALLBACK (ce_page_changed), self);
423
gtk_spin_button_set_value (priv->rate, (gdouble) nm_setting_wireless_get_rate (setting));
424
gtk_spin_button_set_value (priv->tx_power, (gdouble) nm_setting_wireless_get_tx_power (setting));
425
gtk_spin_button_set_value (priv->mtu, (gdouble) nm_setting_wireless_get_mtu (setting));
429
finish_setup (CEPageWifi *self, gpointer unused, GError *error, gpointer user_data)
431
CEPage *parent = CE_PAGE (self);
439
widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wifi_tx_power_label"));
440
gtk_widget_hide (widget);
441
widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wifi_tx_power_hbox"));
442
gtk_widget_hide (widget);
444
widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wifi_rate_label"));
445
gtk_widget_hide (widget);
446
widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wifi_rate_hbox"));
447
gtk_widget_hide (widget);
451
ce_page_wifi_new (NMConnection *connection,
452
GtkWindow *parent_window,
454
NMRemoteSettings *settings,
455
const char **out_secrets_setting_name,
459
CEPageWifiPrivate *priv;
461
g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
463
self = CE_PAGE_WIFI (ce_page_new (CE_TYPE_PAGE_WIFI,
468
UIDIR "/ce-page-wifi.ui",
472
g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("Could not load Wi-Fi user interface."));
476
wifi_private_init (self);
477
priv = CE_PAGE_WIFI_GET_PRIVATE (self);
479
priv->setting = nm_connection_get_setting_wireless (connection);
480
if (!priv->setting) {
481
priv->setting = NM_SETTING_WIRELESS (nm_setting_wireless_new ());
482
nm_connection_add_setting (connection, NM_SETTING (priv->setting));
485
g_signal_connect (self, "initialized", G_CALLBACK (finish_setup), NULL);
487
return CE_PAGE (self);
491
ce_page_wifi_get_ssid (CEPageWifi *self)
493
CEPageWifiPrivate *priv;
494
const char *txt_ssid;
497
g_return_val_if_fail (CE_IS_PAGE_WIFI (self), NULL);
499
priv = CE_PAGE_WIFI_GET_PRIVATE (self);
500
txt_ssid = gtk_entry_get_text (priv->ssid);
501
if (!txt_ssid || !strlen (txt_ssid))
504
ssid = g_byte_array_sized_new (strlen (txt_ssid));
505
g_byte_array_append (ssid, (const guint8 *) txt_ssid, strlen (txt_ssid));
511
ui_to_setting (CEPageWifi *self)
513
CEPageWifiPrivate *priv = CE_PAGE_WIFI_GET_PRIVATE (self);
515
GByteArray *bssid = NULL;
516
GByteArray *device_mac = NULL;
517
GByteArray *cloned_mac = NULL;
522
ssid = ce_page_wifi_get_ssid (self);
524
if (gtk_combo_box_get_active (priv->mode) == 1)
527
mode = "infrastructure";
529
switch (gtk_combo_box_get_active (priv->band)) {
542
entry = gtk_bin_get_child (GTK_BIN (priv->bssid));
544
bssid = ce_page_entry_to_mac (GTK_ENTRY (entry), ARPHRD_ETHER, NULL);
545
entry = gtk_bin_get_child (GTK_BIN (priv->device_mac));
547
device_mac = ce_page_entry_to_mac (GTK_ENTRY (entry), ARPHRD_ETHER, NULL);
548
cloned_mac = ce_page_entry_to_mac (priv->cloned_mac, ARPHRD_ETHER, NULL);
550
g_object_set (priv->setting,
551
NM_SETTING_WIRELESS_SSID, ssid,
552
NM_SETTING_WIRELESS_BSSID, bssid,
553
NM_SETTING_WIRELESS_MAC_ADDRESS, device_mac,
554
NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, cloned_mac,
555
NM_SETTING_WIRELESS_MODE, mode,
556
NM_SETTING_WIRELESS_BAND, band,
557
NM_SETTING_WIRELESS_CHANNEL, gtk_spin_button_get_value_as_int (priv->channel),
558
NM_SETTING_WIRELESS_RATE, gtk_spin_button_get_value_as_int (priv->rate),
559
NM_SETTING_WIRELESS_TX_POWER, gtk_spin_button_get_value_as_int (priv->tx_power),
560
NM_SETTING_WIRELESS_MTU, gtk_spin_button_get_value_as_int (priv->mtu),
564
g_byte_array_free (ssid, TRUE);
566
g_byte_array_free (device_mac, TRUE);
568
g_byte_array_free (cloned_mac, TRUE);
570
g_byte_array_free (bssid, TRUE);
574
validate (CEPage *page, NMConnection *connection, GError **error)
576
CEPageWifi *self = CE_PAGE_WIFI (page);
577
CEPageWifiPrivate *priv = CE_PAGE_WIFI_GET_PRIVATE (self);
580
gboolean invalid = FALSE;
584
entry = gtk_bin_get_child (GTK_BIN (priv->bssid));
586
ignore = ce_page_entry_to_mac (GTK_ENTRY (entry), ARPHRD_ETHER, &invalid);
590
g_byte_array_free (ignore, TRUE);
593
entry = gtk_bin_get_child (GTK_BIN (priv->device_mac));
595
ignore = ce_page_entry_to_mac (GTK_ENTRY (entry), ARPHRD_ETHER, &invalid);
599
g_byte_array_free (ignore, TRUE);
602
ignore = ce_page_entry_to_mac (priv->cloned_mac, ARPHRD_ETHER, &invalid);
606
g_byte_array_free (ignore, TRUE);
608
ui_to_setting (self);
610
/* A hack to not check the wifi security here */
611
security = g_strdup (nm_setting_wireless_get_security (priv->setting));
612
g_object_set (priv->setting, NM_SETTING_WIRELESS_SEC, NULL, NULL);
614
success = nm_setting_verify (NM_SETTING (priv->setting), NULL, error);
615
g_object_set (priv->setting, NM_SETTING_WIRELESS_SEC, security, NULL);
622
ce_page_wifi_init (CEPageWifi *self)
627
ce_page_wifi_class_init (CEPageWifiClass *wifi_class)
629
GObjectClass *object_class = G_OBJECT_CLASS (wifi_class);
630
CEPageClass *parent_class = CE_PAGE_CLASS (wifi_class);
632
g_type_class_add_private (object_class, sizeof (CEPageWifiPrivate));
634
/* virtual methods */
635
parent_class->validate = validate;
640
wifi_connection_new (GtkWindow *parent,
642
NMRemoteSettings *settings,
643
PageNewConnectionResultFunc result_func,
646
NMConnection *connection;
649
connection = ce_page_new_connection (_("Wi-Fi connection %d"),
650
NM_SETTING_WIRELESS_SETTING_NAME,
654
s_wifi = nm_setting_wireless_new ();
655
g_object_set (s_wifi, NM_SETTING_WIRELESS_MODE, "infrastructure", NULL);
656
nm_connection_add_setting (connection, s_wifi);
658
(*result_func) (connection, FALSE, NULL, user_data);