summaryrefslogtreecommitdiffstats
path: root/perl-install/standalone/drakroam
diff options
context:
space:
mode:
Diffstat (limited to 'perl-install/standalone/drakroam')
-rwxr-xr-xperl-install/standalone/drakroam397
1 files changed, 397 insertions, 0 deletions
diff --git a/perl-install/standalone/drakroam b/perl-install/standalone/drakroam
new file mode 100755
index 000000000..bdb25e61c
--- /dev/null
+++ b/perl-install/standalone/drakroam
@@ -0,0 +1,397 @@
+#!/usr/bin/perl
+
+# drakroam: wireless network roaming GUI
+# beta version uses wlandetect as backend
+# Austin Acton, 2004
+# <austin@mandrake.org>
+# Licensed under the GPL
+
+# problems
+# - deletes comments in config file
+# - expects an ifcfg file for static IP configurations (not uncommon)
+# - roaming status fails (no idea why)
+# maybe same reason bash-completion killall can't see wlandetect?
+
+# todo (wlandetect version)
+# - make known and available lists have more rows by default (why so small?)
+# - refresh status every x seconds
+# - find a good way to drop the access point and resume roaming
+# - make 'key' column wider by default
+# todo (waproamd version)
+# - listen to dbus for pings from waproamd; update all on receiving a dbus ping
+# - setup static network configurations
+# - handle keys (can key file be named after ESSID?)
+# - should files be named as MAC or as essid:ESSID ?
+
+use lib qw(/usr/lib/libDrakX);
+
+use standalone;
+use common;
+use run_program;
+
+require ugtk2;
+ugtk2->import(qw(:wrappers :create));
+use Gtk2::SimpleList;
+
+require_root_capability();
+
+# global settings
+my $route = '/sbin/route';
+my $AboutFile = 'ABOUT';
+my $HelpFile = 'README';
+my $IWList = '/sbin/iwlist';
+my $IWConfig = '/sbin/iwconfig';
+my $IFConfig = '/sbin/ifconfig';
+my $IFUp = '/sbin/ifup';
+my $IFDown = '/sbin/ifdown';
+my $DHClient = '/sbin/dhclient';
+
+# initialize variables
+my $ScanInterval = 30; # tell deamon to search for new nets every x seconds
+
+my ($KnownList, $AvailableList);
+my $device;
+
+my %available_roaming_daemons = (
+ wlandetect => {
+ config_location => '/etc/wlandetect.conf',
+ binary => '/usr/sbin/wlandetect',
+ start_options => sub {
+ my ($interval, $device) = @_;
+ "-d -t $interval";
+ },
+ read_config => sub {
+ my ($config) = @_;
+ each_index {
+ /^#/ || /^\n/ and next; #ignore comments and blank lines
+ if (/^(\S+)\s+(.*)$/) {
+ my ($essid, $mode, $channel, $dhcp, $key);
+ my $command = $2;
+ # setup new network entry
+ $essid = $1;
+ ($mode) = $command =~ /mode\s([^\s;]+)/;
+ ($channel) = $command =~ /channel\s([^\s;]+)/;
+ ($key) = $command =~ /key\s([^\s;]+)/;
+ $dhcp = $command =~ /dhclient/;
+ &AddNet($essid, $mode, $channel, $dhcp, $key);
+ }
+ else { die "Line $::i of configuration file is not parseable.\n" }
+ } cat_($config)
+ },
+ write_config => sub {
+ my ($config) = @_;
+ my @contents = (
+ "#wlandetect configuration file\n",
+ "#format: essid<tab><tab>commands\n",
+ "#use \@DEV\@ for device name\n"
+ );
+ foreach my $row (@{$KnownList->{data}}) { # again, lame
+ my $essid = $row->[0];
+ my $iwc = join(' ', $IWConfig, "essid $essid",
+ if_($row->[1], "mode $row->[1]"),
+ if_($row->[2], "channel $row->[2]"),
+ if_($row->[4], "key $row->[4]"));
+ my $ifc = $row->[3] ? "$IFConfig \@DEV\@ up; $DHClient \@DEV\@" : "$IFUp \@DEV\@";
+ push @contents, "$essid\t\t$iwc; $ifc\n";
+ }
+ output_p($config, @contents);
+ },
+ add_net => sub {},
+ remove_net => sub {},
+ },
+ waproamd => {
+ config_location => '/etc/waproamd/scripts',
+ binary => '/usr/sbin/waproamd',
+ start_options => sub {
+ my ($interval, $device) = @_;
+ "-i $device -t $interval";
+ },
+ read_config => sub {
+ my ($config) = @_;
+ foreach my $net (all($config)) {
+ $net eq "default" or next;
+ print "Adding net $net\n";
+ push @{$KnownList->{data}}, [$net];
+ }
+ },
+ write_config => sub {},
+ add_net => sub {
+ my ($config, $essid) = @_;
+ output_p("$config/$essid", qq(# essid specific config file));
+ },
+ remove_net => sub {
+ my ($config, $essid) = @_;
+ system("rm -f $config/$essid");
+ },
+ },
+);
+
+my $roaming_daemon = $available_roaming_daemons{wlandetect};
+
+my $ScanEntry = Gtk2::Entry->new;
+$ScanEntry->set_width_chars(4);
+$ScanEntry->set_text($ScanInterval);
+
+$KnownList = Gtk2::SimpleList->new(
+ "ESSID" => "text",
+ "Mode" => "text",
+ "Channel" => "text",
+ "DHCP" => "bool",
+ "Key" => "text"
+ );
+$KnownList->get_selection->set_mode('single');
+$KnownList->set_reorderable(1);
+$KnownList->set_column_editable(1, TRUE); # allow to change mode
+$KnownList->set_column_editable(2, TRUE); # allow to change channel
+$KnownList->set_column_editable(4, TRUE); # allow to change key
+
+$AvailableList = Gtk2::SimpleList->new(
+ "ESSID" => "text",
+ "Type" => "text",
+ "Encryption" => "text",
+ "Signal (%)" => "int"
+ );
+$AvailableList->get_selection->set_mode('single');
+
+my $NetLabel = Gtk2::Label->new;
+my $IpLabel = Gtk2::Label->new;
+my $GwLabel = Gtk2::Label->new;
+my $ModeLabel = Gtk2::Label->new;
+my $WepLabel = Gtk2::Label->new;
+my $SignalLabel = Gtk2::Label->new;
+
+my $w = ugtk2->new('Drakroam');
+gtkadd(gtkset_border_width($w->{window}, 2),
+ gtkpack_(Gtk2::VBox->new,
+ 0, gtkadd(gtkset_border_width(Gtk2::Frame->new("Status"), 2),
+ gtkpack(Gtk2::VBox->new,
+ create_packtable({ col_spacings => 5, row_spacings => 5, homogenous => 1 },
+ [ $NetLabel, $IpLabel, $GwLabel ],
+ [ $ModeLabel, $WepLabel, $SignalLabel ],
+ ),
+ gtkpack(create_hbox(),
+ gtksignal_connect(Gtk2::Button->new("Disconnect"), clicked => sub { &Disconnect }),
+ gtksignal_connect(Gtk2::Button->new("Refresh"), clicked => sub { &UpdateStatus })
+ )
+ )
+ ),
+ 0, gtkadd(gtkset_border_width(Gtk2::Frame->new("Roaming"), 2),
+ gtkpack(create_hbox(),
+ gtkpack(Gtk2::VBox->new,
+ my $RoamStatus = Gtk2::Label->new("Roaming: off"),
+ gtkpack(create_hbox(),
+ gtksignal_connect(Gtk2::Button->new("Start"), clicked => sub { &StartRoam }),
+ gtksignal_connect(Gtk2::Button->new("Stop"), clicked => sub { &StopRoam })
+ )
+ ),
+ gtkpack(Gtk2::VBox->new,
+ Gtk2::Label->new("Scan interval (sec): "),
+ gtkpack(Gtk2::HBox->new,
+ $ScanEntry,
+ gtksignal_connect(Gtk2::Button->new("Set"), clicked => sub { &SetInterval })
+ )
+ )
+ )
+ ),
+ 1, gtkadd(gtkset_border_width(Gtk2::Frame->new("Known Networks (Drag up/down or edit)"), 2),
+ gtkpack_(Gtk2::VBox->new,
+ 1, create_scrolled_window($KnownList),
+ 0, gtkpack(create_hbox(),
+ gtksignal_connect(Gtk2::Button->new("Remove"), clicked => sub {
+ my ($selected) = $KnownList->get_selected_indices;
+ &RemoveNet($selected);
+ }),
+ gtksignal_connect(Gtk2::Button->new("Connect"), clicked => sub {
+ my ($selected) = $KnownList->get_selected_indices;
+ &ConnectNow($selected);
+ }),
+ gtksignal_connect(Gtk2::Button->new("Save"), clicked => sub { &WriteConfig })
+ )
+ )
+ ),
+ 1, gtkadd(gtkset_border_width(Gtk2::Frame->new("Available Networks"), 2),
+ gtkpack_(Gtk2::VBox->new,
+ 1, create_scrolled_window($AvailableList),
+ 0, gtkpack(create_hbox(),
+ gtksignal_connect(Gtk2::Button->new("Add"), clicked => sub {
+ my @selected = $AvailableList->get_selected_indices;
+ my ($mode, $channel, $key);
+ my $essid = $AvailableList->{data}["@selected"][0];
+ my $dhcp = 1; # assume dhcp for new networks
+ &AddNet($essid, $mode, $channel, $dhcp, $key);
+ }),
+ gtksignal_connect(Gtk2::Button->new("Rescan"), clicked => sub { &UpdateAvailable })
+ )
+ )
+ ),
+ 0, gtkpack(create_hbox(),
+ gtksignal_connect(Gtk2::Button->new("Help"), clicked => sub { &Dialog($HelpFile) }),
+ gtksignal_connect(Gtk2::Button->new("About"), clicked => sub { &Dialog($AboutFile) }),
+ gtksignal_connect(Gtk2::Button->new("Save and close"), clicked => sub {
+ &WriteConfig;
+ Gtk2->main_quit;
+ })
+ )
+ )
+ );
+
+# fill the GUI
+&ReadConfig;
+&UpdateAll;
+
+sub UpdateAll {
+ &UpdateAvailable; #must go first as it defines the device name
+ &UpdateStatus;
+ &UpdateRoaming;
+}
+
+sub isRoamingRunning() {
+ my $name = basename($roaming_daemon->{binary});
+ any { /\Q$name\E$/ } run_program::get_stdout("ps", "-A");
+}
+
+sub UpdateRoaming() {
+ my $status = isRoamingRunning() ? "on" : "off";
+ $RoamStatus->set_text("Roaming: $status");
+ return FALSE; #- do not update again if launched on timeout
+}
+
+sub UpdateStatus() {
+ my $CurrentNet = "-";
+ my $CurrentIP = "---.---.---.---";
+ my $CurrentGW = "---.---.---.---";
+ my $CurrentMode = "";
+ my $CurrentWEP = "";
+ my $CurrentSignal = "-";
+ print("Updating\n");
+ foreach (run_program::get_stdout($IWConfig, $device)) {
+ /ESSID:"(\S*)"/ and $CurrentNet = $1;
+ /Mode:(\S*)\s/ and $CurrentMode = $1;
+ /key:(\S*)\s/ and $CurrentWEP = $1;
+ m!Quality:(\S*)/! and $CurrentSignal = $1;
+ }
+ foreach (run_program::get_stdout($IFConfig, $device)) {
+ if (/inet addr:(\S*)\s/) { $CurrentIP = $1 }
+ }
+ foreach (run_program::get_stdout($route)) {
+ if (/default\s*(\S*)\s/) { $CurrentGW = $1 }
+ else { $CurrentGW = "---.---.---.---" }
+ }
+ $NetLabel->set_text("Net: $CurrentNet");
+ $ModeLabel->set_text("Mode: $CurrentMode");
+ $IpLabel->set_text("IP: $CurrentIP");
+ $WepLabel->set_text("Encryption: $CurrentWEP");
+ $GwLabel->set_text("Gateway: $CurrentGW");
+ $SignalLabel->set_text("Signal: $CurrentSignal");
+}
+
+sub UpdateAvailable() {
+ my ($essid, $mode, $wep, $signal);
+ print("Running iwlist\n");
+ @{$AvailableList->{data}} = ();
+ foreach (run_program::get_stdout($IWList, "scan")) {
+ /([^ ]+)([ \t]+)Scan completed :/ and $device = $1;
+ /([^ ]+)([ \t]+)No scan results/ and $device = $1;
+ /ESSID:"(\S*)"/ and $essid = $1;
+ /Mode:(\S*)/ and $mode = $1;
+ m!Quality:(\S*)/! and $signal = $1;
+ if (/key:(\S*)\s/) {
+ $wep = $1;
+ print("ESSID: $essid, Mode: $mode, WEP: $wep, Signal: $signal\n");
+ push @{$AvailableList->{data}}, [$essid, $mode, $wep, $signal];
+ }
+ }
+}
+
+sub AddNet {
+ my ($essid, $mode, $channel, $dhcp, $key) = @_;
+ print "Adding net $essid\n";
+ push @{$KnownList->{data}}, [ $essid, $mode, $channel, $dhcp, $key ];
+ $_->{add_net}($_->{config_location}, $essid) foreach values %available_roaming_daemons;
+}
+
+sub RemoveNet {
+ my ($selected) = @_;
+ my $essid = $KnownList->{data}[$selected][0];
+ print "Removing net $essid\n";
+ splice @{$KnownList->{data}}, $selected, 1;
+ $_->{remove_net}($_->{config_location}, $essid) foreach values %available_roaming_daemons;
+}
+
+sub ReadConfig() {
+ $_->{read_config}($_->{config_location}) foreach values %available_roaming_daemons;
+}
+
+sub WriteConfig() {
+ $_->{write_config}($_->{config_location}) foreach values %available_roaming_daemons;
+}
+
+sub StartRoam() {
+ my $options = $roaming_daemon->{start_options}($ScanInterval, $device);
+ my $name = basename($roaming_daemon->{binary});
+ system("killall $name; $roaming_daemon->{binary} $options &");
+ Glib::Timeout->add(1000, \&UpdateRoaming);
+}
+
+sub StopRoam() {
+ my $name = basename($roaming_daemon->{binary});
+ system("killall $name");
+ Glib::Timeout->add(1000, \&UpdateRoaming);
+}
+
+sub SetInterval() {
+ $ScanInterval = $ScanEntry->get_text;
+ if (isRoamingRunning()) {
+ StopRoam();
+ StartRoam();
+ }
+}
+
+sub ConnectNow {
+ my ($row) = @_;
+ my @command = "";
+ push @command, "$IWConfig $device essid $KnownList->{data}[$row][0] ";
+ if ($KnownList->{data}[$row][1]) {
+ push @command, "mode $KnownList->{data}[$row][1] ";
+ }
+ if ($KnownList->{data}[$row][2]) {
+ push @command, "channel $KnownList->{data}[$row][2] ";
+ }
+ if ($KnownList->{data}[$row][4]) {
+ push @command, "key $KnownList->{data}[$row][4] ";
+ }
+ push @command, "; ";
+ if ($KnownList->{data}[$row][3]) {
+ push @command, "$IFConfig $device up; $DHClient $device";
+ }
+ else {
+ push @command, "$IFUp $device"
+ }
+ my $ToBash = join("", @command);
+ print("Sending $ToBash\n");
+ system($ToBash);
+ &UpdateStatus;
+}
+
+sub Disconnect {
+ print("Dropping $device\n");
+ system("$IFDown $device");
+ &UpdateStatus;
+}
+
+sub Dialog {
+ my ($FilePointer) = @_;
+ my $content = join('', cat_($FilePointer));
+ # dump into a dialog
+ my $AboutWindow = Gtk2::Dialog->new("Drakroam Info", $w->{window},
+ 'destroy-with-parent',
+ N("Ok") => 'none');
+ $AboutWindow->vbox->add(create_scrolled_window(Gtk2::Label->new($content)));
+ $AboutWindow->signal_connect(response => sub { $_[0]->destroy });
+ $AboutWindow->show_all;
+}
+
+# start GUI
+print "Starting GUI\n";
+
+$w->main;