summaryrefslogtreecommitdiffstats
path: root/bin/drakroam
diff options
context:
space:
mode:
Diffstat (limited to 'bin/drakroam')
-rwxr-xr-xbin/drakroam405
1 files changed, 253 insertions, 152 deletions
diff --git a/bin/drakroam b/bin/drakroam
index 5511e76..a642aec 100755
--- a/bin/drakroam
+++ b/bin/drakroam
@@ -2,12 +2,14 @@
# drakroam: wireless network roaming GUI
# Austin Acton, 2004 <austin@mandriva.org>
-# Olivier Blin, 2005 <oblin@mandriva.com>
+# Olivier Blin, 2005-2006 <oblin@mandriva.com>
# Licensed under the GPL
use strict;
use lib qw(/usr/lib/libDrakX);
+# i18n: IMPORTANT: to get correct namespace (drakx-net instead of libDrakX)
+BEGIN { unshift @::textdomains, 'drakx-net' }
use standalone;
use common;
use run_program;
@@ -16,33 +18,104 @@ use interactive;
use mygtk2;
use ugtk2 qw(:create :helpers :wrappers);
use Gtk2::SimpleList;
-use network::ethernet;
use network::monitor;
+use network::signal_strength;
use network::network;
use network::tools;
-use network::wireless;
-
+use network::connection;
+use network::connection::wireless;
+use network::connection::cellular_card;
+use modules;
+
+my $title = N("Wireless connection");
+my $icon = '/usr/share/mcc/themes/default/drakroam-mdk.png';
+
+$ugtk2::wm_icon = $icon;
+my $w = ugtk2->new($title);
+#- so that transient_for is defined, for wait messages and popups to be centered
+$::main_window = $w->{real_window};
my $in = 'interactive'->vnew('su');
-my $arg_ap;
-/^--ap=(.*)/ and $arg_ap = $1 foreach @ARGV;
+my %args = map { if_(/^--(\w+)=(.*)$/ && member($1, qw(ap interface)), $1 => $2) } @ARGV;
+
+my @connection_types = qw(network::connection::wireless network::connection::cellular_card);
+my @connections;
+my $connection;
+
+my %buttons;
+
+my $model = Gtk2::ListStore->new('Gtk2::Gdk::Pixbuf', 'Glib::String');
+my $connections_combo = Gtk2::ComboBox->new($model);
+$connections_combo = Gtk2::ComboBox->new($model);
+my $pix_r = Gtk2::CellRendererPixbuf->new;
+$connections_combo->pack_start($pix_r, 0,);
+$connections_combo->add_attribute($pix_r, pixbuf => 0);
+my $text_r = Gtk2::CellRendererText->new;
+$connections_combo->pack_start($text_r, 1);
+$connections_combo->add_attribute($text_r, text => 1);
+
+my $pixbuf_size = 32;
+my $empty_pixbuf = Gtk2::Gdk::Pixbuf->new('rgb', 1, 8, $pixbuf_size, $pixbuf_size);
+$empty_pixbuf->fill(0);
+
+sub update_connections_list() {
+ $model->set($model->append, 0, $empty_pixbuf , 1, N("No device found")) unless @connections;
+ $model->set($model->append,
+ 0, gtknew('Pixbuf', file => $_->get_type_icon)->scale_simple($pixbuf_size, $pixbuf_size, 'hyper'),
+ 1, $_->get_description) foreach @connections;
+ my $index = $connection && eval { find_index { $_ == $connection } @connections };
+ $connections_combo->set_active($index) if defined $index;
+}
-my $wireless_device = detect_devices::get_wireless_interface();
+sub get_connection() {
+ @connections or return;
+ my $index = $connections_combo->get_active;
+ defined $index && $connections[$index];
+}
-unless ($wireless_device) {
- ugtk2::err_dialog(N("Error"), N("You do not have any wireless interface.
-Run the \"%s\" assistant from the Mandriva Linux Control Center", N("Set up a new network interface (LAN, ISDN, ADSL, ...)")));
- ugtk2::exit(0) if !$::testing;
+sub prepare_connection() {
+ my @packages = $connection->can('get_packages') ? $connection->get_packages : ();
+ if (@packages && !$in->do_pkgs->install(@packages)) {
+ $in->ask_warn(N("Error"), N("Could not install the packages (%s)!", join(', ', @packages)));
+ return;
+ }
+ $connection->prepare_device;
+ $connection->setup_thirdparty($in) or return;
+ if ($connection->can("check_device") && !$connection->check_device) {
+ $in->ask_warn(N("Error"), $connection->{device}{error});
+ return;
+ }
+ if ($connection->can('get_hardware_settings')) {
+ $connection->guess_hardware_settings if $connection->can('guess_hardware_settings');
+ $in->ask_from_({
+ title => "Network settings",
+ messages => N("Please enter settings for network")
+ }, $connection->get_hardware_settings) or return;
+ }
+ if ($connection->can('check_hardware')) {
+ my $_w = $in->wait_message('', N("Configuring device..."));
+ if (!$connection->check_hardware) {
+ $in->ask_warn(N("Error"), $connection->{hardware}{error}) if $connection->{hardware}{error};
+ return;
+ }
+ }
}
-my $modules_conf = modules::any_conf->read;
-my $dev = find { $_->[0] eq $wireless_device } network::ethernet::get_eth_cards($modules_conf);
-my $wireless_module = $dev->[1];
+sub select_connection() {
+ $connection = get_connection();
+ prepare_connection() if $connection;
+ update_on_connection_change();
+}
+
+sub update_on_connection_change() {
+ $buttons{refresh}->set_sensitive(to_bool($connection));
+ update_networks();
+}
my $net = {};
network::network::read_net_conf($net);
-my $wireless_list = Gtk2::SimpleList->new(
+my $networks_list = Gtk2::SimpleList->new(
"AP" => "hidden",
'' => "pixbuf",
N("SSID") => "text",
@@ -51,13 +124,39 @@ my $wireless_list = Gtk2::SimpleList->new(
N("Encryption") => "text",
N("Operating Mode") => "text",
);
-$wireless_list->get_selection->set_mode('single');
+$networks_list->get_selection->set_mode('single');
+
+my $status_bar = Gtk2::Statusbar->new;
+my $status_bar_cid = $status_bar->get_context_id("Network event");
+
+sub get_network_event_message {
+ my ($member, @args) = @_;
+ #- FIXME: the hostname.d script and s2u use a different D-Bus interface
+ if ($member eq 'hostname') {
+ my ($hostname) = @args;
+ N("Hostname changed to \"%s\"", $hostname);
+ } elsif ($member eq 'status') {
+ my ($status, $interface) = @args;
+ my $event_connection = find { $_->get_interface eq $interface } @connections;
+ $event_connection && $event_connection->get_status_message($status);
+ }
+}
-my ($dbus, $monitor);
+my $dbus;
eval { $dbus = dbus_object::system_bus() };
-eval { $monitor = network::monitor->new($dbus) } if $dbus;
-my $wireless_networks = {};
-my $has_roaming;
+if ($dbus) {
+ eval { $net->{monitor} = network::monitor->new($dbus) };
+ $dbus->{connection}->add_filter(sub {
+ my ($_con, $msg) = @_;
+ my $member = $msg->get_member;
+ my $message = get_network_event_message($member, $msg->get_args_list) or return;
+ my $m_id = $status_bar->push($status_bar_cid, $message);
+ Glib::Timeout->add(20000, sub { $status_bar->remove($status_bar_cid, $m_id); 0 });
+ update_networks() if $member eq 'status';
+ });
+ $dbus->{connection}->add_match("type='signal',interface='com.mandriva.network'");
+ dbus_object::set_gtk2_watch_helper($dbus);
+}
my %pixbufs =
(
@@ -65,174 +164,176 @@ my %pixbufs =
link_level => { map {
$_ => gtkcreate_pixbuf('wifi-' . sprintf('%03d', $_) . '.png')->scale_simple(24, 24, 'hyper');
} qw(20 40 60 80 100) },
- keyring => gtkcreate_pixbuf("/usr/share/pixmaps/keyring-small.png")->scale_simple(24, 24, 'hyper'), #- provided by usermode, required by drakxtools
+ encryption => { map {
+ $_ => gtkcreate_pixbuf("encryption-$_-24.png");
+ } qw(open weak strong) },
);
sub update_networks() {
- ($wireless_networks, $has_roaming) = network::monitor::list_wireless($monitor, $wireless_device);
- @{$wireless_list->{data}} = ();
-
- my $routes = network::tools::get_routes();
- my $connected = exists $routes->{$wireless_device}{network};
-
- while (my ($ap, $network) = each(%$wireless_networks)) {
- push @{$wireless_list->{data}}, [
- $ap,
- $network->{current} ? $connected ? $pixbufs{state}{connected} : $pixbufs{state}{refresh} : undef,
- $network->{essid} || exists $net->{wireless}{$ap} && $net->{wireless}{$ap}{WIRELESS_ESSID} || "[$ap]",
- $pixbufs{link_level}{$network->{approx_level}},
- $network->{flags} ? $pixbufs{keyring} : undef,
- $network->{flags},
- $network->{mode},
- ];
+ @{$networks_list->{data}} = ();
+
+ if ($connection) {
+ my $wait = $connection->network_scan_is_slow && $in->wait_message('', N("Scanning for networks..."));
+ $connection->{networks} = $connection->get_networks;
+ undef $wait;
+
+ $connection->{network} ||= find { $connection->{networks}{$_}{current} } keys %{$connection->{networks}};
+
+ my $routes = network::tools::get_routes();
+ my $interface = $connection->get_interface;
+ my $connected = exists $routes->{$interface}{network};
+
+ while (my ($ap, $network) = each(%{$connection->{networks}})) {
+ push @{$networks_list->{data}}, [
+ $ap || $network->{name},
+ $network->{current} ? $connected ? $pixbufs{state}{connected} : $pixbufs{state}{refresh} : undef,
+ !$network->{essid} && exists $net->{wireless}{$ap} && $net->{wireless}{$ap}{WIRELESS_ESSID} || $network->{name},
+ network::signal_strength::get_strength_icon($network),
+ $pixbufs{encryption}{$network->{flags} =~ /WPA/i ? 'strong' : $network->{flags} =~ /WEP/i ? 'weak' : 'open'},
+ $network->{flags},
+ $network->{mode},
+ ];
+ }
+
+ if ($connection->{network}) {
+ my $index = eval { find_index { $_->[0] eq $connection->{network} } @{$networks_list->{data}} };
+ $networks_list->select($index) if defined $index;
+ }
}
- 1;
-}
-sub configure_ap {
- my ($ap) = @_;
- my $network = $wireless_networks->{$ap};
- my $essid = $network->{essid};
- my $wireless_net =
- $essid && exists $net->{wireless}{$essid} ?
- $net->{wireless}{$essid} :
- exists $net->{wireless}{$ap} ?
- $net->{wireless}{$ap} :
- {};
- $wireless_net->{WIRELESS_ESSID} = $essid if $essid;
+ update_on_network_change();
+}
- my ($wireless_enc_mode, $wireless_enc_key, $wireless_restricted);
- ($wireless_enc_key, $wireless_restricted) = network::wireless::get_wep_key_from_iwconfig($wireless_net->{WIRELESS_ENC_KEY});
- $wireless_enc_mode = $network->{flags} =~ /wpa/i ? 'wpa-psk' : $network->{flags} =~ /wep/i ? $wireless_restricted ? 'restricted' : 'open' : 'none';
+sub load_settings() {
+ $connection->load_interface_settings;
+ $connection->guess_network_access_settings if $connection->can('guess_network_access_settings');
+ $connection->guess_protocol($net) if $connection->can('guess_protocol');
+ $connection->guess_access_settings if $connection->can('guess_access_settings');
+ $connection->guess_address_settings if $connection->can('guess_address_settings');
+ $connection->guess_hostname_settings if $connection->can('guess_hostname_settings');
+ $connection->guess_network_control_settings if $connection->can('guess_network_control_settings');
+ $connection->guess_control_settings;
+}
- my $dhcp = to_bool(!exists($wireless_net->{BOOTPROTO}) || $wireless_net->{BOOTPROTO} eq "dhcp");
+sub configure_network() {
+ load_settings();
$in->ask_from_({
- title => "Wireless settings",
- messages => N("Please enter settings for wireless network \"%s\"", $essid || $ap)
+ title => "Network settings",
+ messages => N("Please enter settings for network")
},
[
- { label => N("Network name (ESSID)"), val => \$wireless_net->{WIRELESS_ESSID}, disabled => sub { $essid } },
- { label => N("Encryption mode"), val => \$wireless_enc_mode,
- list => [ keys %network::wireless::wireless_enc_modes ],
- sort => 1,
- format => sub { translate($network::wireless::wireless_enc_modes{$_[0]}) } },
- { label => N("Encryption key"), val => \$wireless_enc_key, disabled => sub { $wireless_enc_mode eq 'none' } },
- { text => N("Automatic IP (BOOTP/DHCP)"), val => \$dhcp, type => 'bool' },
- { label => N("IP address"), val => \$wireless_net->{IPADDR}, disabled => sub { $dhcp } },
- { label => N("DNS server"), val => \$wireless_net->{MS_DNS1}, disabled => sub { $dhcp } },
- { label => N("Gateway IP address"), val => \$wireless_net->{GATEWAY}, disabled => sub { $dhcp } },
+ $connection->can('get_network_access_settings') ? (
+ { label => $connection->get_network_access_settings_label, title => 1, advanced => 1 },
+ @{$connection->get_network_access_settings},
+ ) : (),
+ $connection->can('get_protocols') ? (
+ @{$connection->get_protocol_settings},
+ ) : (),
+ $connection->can('get_access_settings') ? (
+ { label => $connection->get_access_settings_label, title => 1, advanced => 1 },
+ @{$connection->get_access_settings}
+ ) : (),
+ $connection->can('get_address_settings') ? (
+ { label => $connection->get_address_settings_label, title => 1, advanced => 1 },
+ @{$connection->get_address_settings('show_all')}
+ ) : (),
+ $connection->can('get_network_control_settings') ? (
+ @{$connection->get_network_control_settings}
+ ) : (),
],
) or return;
- $wireless_net->{BOOTPROTO} = $dhcp ? 'dhcp' : 'static';
- $wireless_net->{WIRELESS_ENC_KEY} = $wireless_enc_key && network::wireless::convert_wep_key_for_iwconfig($wireless_enc_key, $wireless_enc_mode eq 'restricted');
- $wireless_net->{WIRELESS_MODE} = $network->{mode} eq 'Ad-Hoc' ? $network->{mode} : 'Managed';
-
- if ($has_roaming || $wireless_enc_mode eq 'wpa-psk') {
- $wireless_net->{WIRELESS_WPA_DRIVER} = network::wireless::wpa_supplicant_get_driver($wireless_module);
- network::wireless::wpa_supplicant_add_network($wireless_net->{WIRELESS_ESSID}, $wireless_enc_mode, $wireless_enc_key);
- } else {
- delete $wireless_net->{WIRELESS_WPA_DRIVER};
- }
-
- my $ssid = $essid || $ap;
- $net->{wireless}{$ssid} = $wireless_net;
+ $connection->install_packages($in) if $connection->can('install_packages');
+ $connection->unload_connection if $connection->can('unload_connection');
- network::network::write_wireless_conf($ssid, $wireless_net);
-
- if ($has_roaming) {
- #- this should be handled by the monitoring daemon instead
- run_program::run('/usr/sbin/wpa_cli', 'reconfigure');
- } else {
- overwrite_wireless_ifcfg($wireless_net);
- }
+ my $modules_conf = modules::any_conf->read;
+ $connection->write_settings($net, $modules_conf);
+ $modules_conf->write;
1;
}
-sub overwrite_wireless_ifcfg {
- my ($wireless_net) = @_;
- my $ifcfg = $net->{ifcfg}{$wireless_device} ||= {};
- delete $ifcfg->{$_} foreach grep { /wireless/i } keys %$ifcfg;
- put_in_hash($ifcfg, $wireless_net);
- network::network::write_interface_conf($net, $wireless_device);
-}
-
-sub wait_and_run_sub {
- my ($time, $sub) = @_;
- gtkset_mousecursor_wait();
- Glib::Timeout->add($time, sub {
- $sub->();
- gtkset_mousecursor_normal();
- 0;
- });
-}
-
-sub connect_to_ap {
- my ($ap, $o_disable_configure) = @_;
- my $network = $wireless_networks->{$ap};
- my $found;
-
- if ($network) {
- my $wireless_net = !$has_roaming && ($net->{wireless}{$ap} || $net->{wireless}{$network->{essid}});
- if (defined $network->{id}) {
- eval { $monitor->select_network($network->{id}) };
- $found = !$@;
- $found or ugtk2::err_dialog(N("Wireless connection"), N("Unable to contact daemon"));
- } elsif ($wireless_net) {
- network::tools::stop_interface($wireless_device, 0);
- overwrite_wireless_ifcfg($wireless_net);
- network::tools::start_interface($wireless_device, 1);
- $found = 1;
+sub connect_to_network() {
+ if ($connection->selected_network_is_configured || configure_network()) {
+ gtkset_mousecursor_wait($w->{window}->window);
+ my $_wait = $in->wait_message(N("Please wait"), N("Connecting..."));
+ #- settings have to be rewritten only if they are impacted by choices from the main window
+ if ($connection->can('get_networks')) {
+ load_settings();
+ $connection->write_settings($net);
}
+ $connection->prepare_connection if $connection->can('prepare_connection');
+ $connection->disconnect;
+ $connection->connect($in, $net);
+ gtkset_mousecursor_normal($w->{window}->window);
}
+}
- $found || !$o_disable_configure or return;
-
- if (!$found) {
- if ($has_roaming) {
- configure_ap($ap);
- #- wait for wpa_supplicant to reconfigure the device
- wait_and_run_sub(2000, sub { connect_to_ap($ap, 1) });
- return;
- } else {
- network::tools::stop_interface($wireless_device, 0);
- configure_ap($ap);
- network::tools::start_interface($wireless_device, 0);
- }
+sub select_network() {
+ if ($connection) {
+ my ($selected) = $networks_list->get_selected_indices;
+ $connection->{network} = defined $selected && $networks_list->{data}[$selected][0];
}
- wait_and_run_sub(10000, \&update_networks);
+ update_on_network_change();
}
-sub configure_selected() {
- my ($selected) = $wireless_list->get_selected_indices or return;
- configure_ap($wireless_list->{data}[$selected][0]);
+sub update_on_network_change() {
+ $buttons{connect}->set_label(toggle_would_disconnect() ? N("Disconnect") : N("Connect"));
+ #- always allow to disconnect if connected
+ $buttons{connect}->set_sensitive($connection && ($connection->get_status || $connection->{network}));
+ #- allow to configure only if a network is selected
+ $buttons{configure}->set_sensitive($connection && $connection->{network});
}
-sub connect_to_selected() {
- my ($selected) = $wireless_list->get_selected_indices or return;
- connect_to_ap($wireless_list->{data}[$selected][0]);
+sub toggle_would_disconnect() {
+ my $network = $connection && $connection->get_selected_network;
+ $connection && $connection->get_status &&
+ (!$network || keys(%{$connection->{networks}}) <= 1 || $network->{current});
}
-update_networks();
+sub toggle_connection() {
+ if (toggle_would_disconnect()) {
+ gtkset_mousecursor_wait($w->{window}->window);
+ my $_wait = $in->wait_message(N("Please wait"), N("Disconnecting..."));
+ $connection->disconnect;
+ gtkset_mousecursor_normal($w->{window}->window);
+ } elsif ($connection) {
+ $connection->{network} or return;
+ connect_to_network();
+ }
+ update_on_network_change();
+}
-my $w = ugtk2->new(N("Wireless connection"));
gtkadd($w->{window},
gtknew('VBox', spacing => 5, children => [
- $::isEmbedded ? () : (0, Gtk2::Banner->new('/usr/share/mcc/themes/default/drakroam-mdk.png', N("Wireless connection"))),
- 1, gtknew('HBox', spacing => 5, children => [
- 1, gtknew('ScrolledWindow', width => 500, height => 300, child => $wireless_list),
- 0, gtknew('VButtonBox', layout => 'edge', children_loose => [
- gtknew('Button', text => N("Configure"), clicked => \&configure_selected),
- gtknew('Button', text => N("Connect"), clicked => \&connect_to_selected),
- gtknew('Button', text => N("Refresh"), clicked => \&update_networks),
+ $::isEmbedded ? () : (0, Gtk2::Banner->new($icon, $title)),
+ 0, gtknew('HBox', children_tight => [ gtknew('Label_Left', text => N("Device: "), alignment => [ 0.5, 0.5 ]),
+ gtksignal_connect($connections_combo, changed => \&select_connection) ]),
+ 1, gtknew('ScrolledWindow', width => 500, height => 300, child => $networks_list),
+ 0, gtknew('HButtonBox', layout => 'edge', children_loose => [
+ $buttons{configure} = gtknew('Button', text => N("Configure"), clicked => \&configure_network),
+ $buttons{connect} = gtknew('Button', relief => 'half', clicked => \&toggle_connection),
+ $buttons{refresh} = gtknew('Button', text => N("Refresh"), clicked => \&update_networks),
gtknew('Button', text => N("Quit"), clicked => sub { Gtk2->main_quit })
- ]),
]),
+ 0, $status_bar,
]),
);
+$networks_list->get_selection->signal_connect('changed' => \&select_network);
+
+$w->show;
-$arg_ap and Glib::Timeout->add(100, sub { connect_to_ap($arg_ap); 0 });
+@connections = map { $_->get_connections(automatic_only => 1) } @connection_types;
+$connection = $args{interface} && find { $_->get_interface eq $args{interface} } @connections;
+$connection ||= find { !$_->network_scan_is_slow } @connections;
+update_connections_list();
+update_on_connection_change();
+
+if ($args{ap} && $connection) {
+ $connection->{network} = $args{ap};
+ $w->{window}->show_all;
+ connect_to_network();
+}
$w->main;