guifi.pl
Code: Select all
#!/usr/bin/perl -w
#
# Güífi es una IGC (interfaz gráfica cutre) para iwlist, iwconfig y dhclient
# Permite ver redes guáirles (siempre que tengan ESSID broadcast habilitado),
# unirse a las mismas y solicitar IP automática o especificarla manualmente,
# recordando los parámetros WIFI e IP configurados para cada AP.
#
# Requiere nivel de root (o los permisos adecuados en sudoers)
#
# Requiere los paquetes: libgtk2-perl y wireless-tools (y todo lo que esto
# a su vez requiera xD), que se incluyen en LinEspa. Para quien use
# otra distro, se instalan de la siguiente manera:
#
# en Debian y derivados: apt-get install libgtk2-perl wireless-tools
# en RedHat y derivados (NPI, pero supongo que será):
# yum install libgtk2-perl wireless-tools
#
# Licenciado bajo GPL (http://www.gnu.org/copyleft/gpl.html)
# Autor: Julian Coccia (http://julian.coccia.com)
# http://www.linespa.com
#
# Nota: Perl es DOLOROSO y más aún cuando no se tiene mucha idea (como es mi caso)
# Si tienes sugerencias para mejorar el código, estaré muy agradecido. Julian.
#
# Cambios en 0.03:
# - Botón "Conectar y Salir" agregado
# - Sección "Configuracion" reorganizada
# - Función de conectado automático (al buscar redes
# conectar automáticamente si encuentra alguna marcada "auto"
# mediante el checkbox "Conectar Automaticamente")
#
# Cambios en 0.02:
# - Ahora se permite definir en ESSID, en caso de que esté oculto
# - Aclaración sobre la definición de WEPs en ASCII usando s:
#
use Gtk2 -init;
use Gtk2::SimpleList;
my $version="0.03";
# Read Configuration
#
my $cfg = new ManageConfig;
`touch ~/.guifirc`;
$cfg->read_config(`ls ~/.guifirc`);
my $actual_mac="";
# Create main guindow xD
#
my $command;
my $win = Gtk2::Window->new;
$win->set_title ('LinEspa | Gestor Guífi v'.$version);
$win->set_border_width (6);
$win->set_default_size (500, 500);
$win->signal_connect (delete_event => sub { Gtk2->main_quit; });
# Create Network List
#
my $box1 = Gtk2::VBox->new (0,3);
$win->add ($box1);
my $scwin = Gtk2::ScrolledWindow->new;
$box1->pack_start ($scwin, 1, 1, 0);
$scwin->set_policy (qw/automatic automatic/);
my $slist = Gtk2::SimpleList->new (
'Nro' => 'text',
'Nombre' => 'text',
'Cifrado' => 'text',
'Canal' => 'text',
'Señal' => 'text',
'Calidad' => 'text',
'Protocolo' => 'text',
'Dirección' => 'text',
);
$scwin->add ($slist);
my $box2 = Gtk2::HBox->new (0, 6);
$box1->pack_start($box2, 0, 1, 0);
# Create Buttons
#
my $btn;
my $tooltips = Gtk2::Tooltips->new;
foreach (
[ 'Buscar', 'Buscar nuevamente todas las redes visibles' ],
[ 'Conectar', 'Conectar a la red seleccionada' ],
[ 'Desconectar', 'Desconectarse de la red actual' ],
)
{
$btn = Gtk2::Button->new ($_->[0]);
$btn->signal_connect (clicked => \&btn_clicked, $_->[0]);
$tooltips->set_tip ($btn, $_->[1]);
$box2->pack_start($btn, 0, 1, 0);
}
$tooltips->enable;
$btn = Gtk2::Button->new_from_stock ('gtk-quit');
$btn->signal_connect (clicked => sub {
$cfg->save_config();
Gtk2->main_quit; });
$box2->pack_end($btn, 0, 1, 0);
$btn = Gtk2::Button->new ('Conectar y Salir');
$btn->signal_connect (clicked => sub {
AutoConectar();
Gtk2->main_quit;
});
$box2->pack_end($btn, 0, 1, 0);
$slist->get_selection->signal_connect (changed => sub {
read_config();
});
my $dslist = $slist->{data};
my $op_count = 0;
my @pixbufs;
foreach (qw/gtk-ok gtk-cancel gtk-quit gtk-apply gtk-clear
gtk-delete gtk-execute gtk-dnd/)
{
push @pixbufs, $win->render_icon ($_, 'menu');
}
push @pixbufs, undef;
# Status Tabs
#
my $redes = Gtk2::HBox->new(1,6);
$box1->pack_start($redes, 0, 1, 0);
my $status = Gtk2::VBox->new(1,6);
$redes->pack_start($status, 0, 1, 0);
my $frame1 = Gtk2::Frame->new("Red WI-FI actual");
$status->pack_start($frame1, 0, 0, 10);
my $cajavert2 = Gtk2::VBox->new(1);
$frame1->add($cajavert2);
$cajahoriz=show_data($cajavert2,"Adaptor:");
my $adaptador = Gtk2::Label->new('No se encontró adaptador WI-FI');
$cajahoriz->pack_start($adaptador, 0,1, 0);
$cajahoriz=show_data($cajavert2,"Access Point:");
my $accesspoint = Gtk2::Label->new('Sin Conexión');
$cajahoriz->pack_start($accesspoint, 0,1, 0);
$cajahoriz=show_data($cajavert2,"Velocidad:");
my $velocidad = Gtk2::Label->new('No disponible');
$cajahoriz->pack_start($velocidad, 0,1, 0);
$cajahoriz=show_data($cajavert2,"Calidad:");
my $calidad = Gtk2::Label->new('No disponible');
$cajahoriz->pack_start($calidad, 0,1, 0);
$cajahoriz=show_data($cajavert2,"Señal:");
my $senal = Gtk2::Label->new('No disponible');
$cajahoriz->pack_start($senal, 0,1, 0);
my $frame2 = Gtk2::Frame->new("Información IP actual");
$status->pack_start($frame2, 0, 0, 10);
$cajavert2 = Gtk2::VBox->new(1);
$frame2->add($cajavert2);
$cajahoriz=show_data($cajavert2,"Dirección IP:");
my $dirIP = Gtk2::Label->new('Sin Direccion IP');
$cajahoriz->pack_start($dirIP, 0,1, 0);
$cajahoriz=show_data($cajavert2,"Estado:");
my $if_estado = Gtk2::Label->new('Interfaz Desactivada (DOWN)');
$cajahoriz->pack_start($if_estado, 0,1, 0);
$cajahoriz=show_data($cajavert2,"Ruteador:");
my $gateway = Gtk2::Label->new('Sin Ruteador');
$cajahoriz->pack_start($gateway, 0,1, 0);
$cajahoriz=show_data($cajavert2,"DNS:");
my $dns = Gtk2::Label->new('Sin DNS');
$cajahoriz->pack_start($dns, 0,1, 0);
$cajahoriz=show_data($cajavert2,"Tx/Rx:");
my $txrx = Gtk2::Label->new('0/0');
$cajahoriz->pack_start($txrx, 0,1, 0);
# CONFIGURATION SECTION
#
my $frame3 = Gtk2::Frame->new("Modificar configuración ");
$redes->pack_start($frame3, 0, 0, 10);
$cajavert2 = Gtk2::VBox->new(1);
$frame3->add($cajavert2);
# Cambiar Configuración WLAN
#
$cajahoriz= Gtk2::HBox->new(1);
$cajavert2->add($cajahoriz);
my $myessid = input_data($cajahoriz,"ESSID:");
my $automatico = new Gtk2::CheckButton("Conectar automaticamente");
$cajahoriz->add($automatico);
$cajahoriz= Gtk2::HBox->new(1);
$cajavert2->add($cajahoriz);
my $WEP1 = input_data($cajahoriz,"WEP 1:");
my $WEP2 = input_data($cajahoriz,"WEP 2:");
$cajahoriz= Gtk2::HBox->new(1);
$cajavert2->add($cajahoriz);
my $WEP3 = input_data($cajahoriz,"WEP 3:");
my $WEP4 = input_data($cajahoriz,"WEP 4:");
$cajahoriz= Gtk2::HBox->new(1);
$cajavert2->add($cajahoriz);
my $canal = input_data($cajahoriz,"Canal:");
$cajahoriz=show_data($cajahoriz," para claves ASCII anteponer s:");
# Cambiar Configuración IP
#
$cajahoriz= Gtk2::HBox->new(1);
$cajavert2->add($cajahoriz);
my $manual_ip = input_data($cajahoriz,"Dir.IP:");
my $manual_subnet = input_data($cajahoriz,"Mascara:");
$cajahoriz= Gtk2::HBox->new(1);
$cajavert2->add($cajahoriz);
my $manual_gw = input_data($cajahoriz,"Ruteador:");
my $manual_dns = input_data($cajahoriz,"DNS:");
# Botón APLICAR
#
$cajahoriz = Gtk2::HBox->new(0, 3);
$cajavert2->pack_start($cajahoriz, 0,1, 0);
$btn = Gtk2::Button->new ('Aplicar');
$btn->signal_connect (clicked => \&apply_config);
$cajahoriz->pack_end($btn, 0, 1, 0);
# Botón GRABAR
#
$btn = Gtk2::Button->new ('Grabar');
$btn->signal_connect (clicked => \&grabar_config);
$cajahoriz->pack_end($btn, 0, 1, 0);
# Botón OBTENER IP
#
$btn = Gtk2::Button->new ('Solicitar IP vía DHCP');
$btn->signal_connect (clicked => \&dhcp_client);
$cajahoriz->pack_end($btn, 0, 1, 0);
my $id = Glib::Timeout->add (1000, sub {
guifi_estado_wifi();
guifi_estado_IP();
1;
});
$win->show_all;
guifi_scan();
CheckAutoconnect();
Gtk2->main;
# Subroutines Below (ManageConfig module at the bottom)
#
sub guifi_scan
{
my ($cell, $mac, $essid, $linea, $key, $channel, $quality, $signal, $protocol);
my $numredes=0;
my $iface = guifi_interface();
# Clear list
@{$slist->{data}} = ();
# Execute iwlist
$command="iwlist $iface scan";
$cell="";
$essid="";
foreach (`$command`)
{
$linea=$_;
if ($linea =~ /Cell\ / && $essid) {
push(@{$slist->{data}}, [$cell,$essid,$key,$channel,$signal,$quality,$protocol,$mac]);
if (!$cfg->{"$mac"}) { $cfg->set("$mac.essid",$essid); }
$cell="";
$mac="";
$essid="";
$key="";
$channel="";
$quality="";
$signal="";
$protocol="";
$numredes++; }
if ($linea =~ /^.*Cell\ (.*)\ -\ Address: (.*)/) {
$cell = $1;
$mac = $2;
}
if ($linea =~ /^.*ESSID\:"(.*)"/) {
$essid = $1;
}
if ($linea =~ /^.*on\ key\:(.*)/) {
$key = $1;
}
if ($linea =~ /^.*Protocol:(.*)/) {
$protocol = $1;
}
if ($linea =~ /^.*Quality:(.*).*Signal\ level\:(.*)\ N/) {
$quality = $1;
$signal = $2;
}
if ($linea =~ /^.*Signal\:(.*)/) {
$signal = $1;
}
if ($linea =~ /^.*\(Channel\ (.*)\)/) {
$channel = $1;
}
if ($linea =~ /^.*Channel:(.*)/) {
$channel = $1;
}
if ($linea =~ /^.*Bit\ Rate:(.*)/) {
$quality = $1;
}
}
if ($cell) {
push(@{$slist->{data}}, [$cell,$essid,$key,$channel,$signal,$quality,$protocol,$mac]);
if (!$cfg->{"$mac"}) { $cfg->set("$mac.essid",$essid); }
$numredes++;
}
if ($numredes==0) {
push(@{$slist->{data}}, ["", "No hay redes disponibles"]);
}
} # end guifi_scan
sub dhcp_client
{
my $iface = guifi_interface();
`killall -9 dhclient`;
`dhclient $iface`;
}
sub input_data {
my ($donde, $texto) = @_;
my $tmpbox = Gtk2::HBox->new(0, 3);
$donde->pack_start($tmpbox, 0,1, 0);
$tmpbox->pack_start(Gtk2::Label->new($texto),0,1, 0);
my $tmpvar = Gtk2::Entry->new;
$tmpbox->pack_start ($tmpvar, TRUE, TRUE, 0);
return $tmpvar;
}
sub show_data {
my ($donde, $texto) = @_;
my $tmpbox = Gtk2::HBox->new(0, 3);
$donde->pack_start($tmpbox, 0,1, 0);
$tmpbox->pack_start(Gtk2::Label->new($texto),0,1, 0);
return $tmpbox;
}
sub btn_clicked
{
my ($button, $op) = @_;
my $indice;
my $iface;
if( $op eq 'Delete' )
{
delete $dslist->[$#$dslist/2];
}
elsif( $op eq 'Buscar' )
{
guifi_scan;
CheckAutoconnect();
}
elsif( $op eq 'Desconectar' )
{
$iface = guifi_interface();
`iwconfig $iface essid off/any`;
`killall -9 dhclient`;
`ifconfig $iface down`;
}
elsif( $op eq 'Conectar' )
{
$iface = guifi_interface();
$indice=join(", ", $slist->get_selected_indices);
my $ap=$slist->{data}[$indice][1];
`iwconfig $iface essid $ap`;
}
1;
} # end btn_clicked
sub AutoConectar {
btn_clicked("Conectar");
apply_config();
if (!$manual_ip->get_text) {
dhcp_client();
}
}
sub guifi_interface {
my $iface;
foreach (`cat /proc/net/wireless`) {
if (/\ (.*):/) {
$iface=$1;
}
}
$adaptador->set_text($iface);
return $iface;
} # end guifi_interface
sub guifi_estado_wifi {
my $iface = guifi_interface();
# Execute iwconfig
$command="iwconfig $iface";
my ($bitrate,$essid);
foreach (`$command`)
{
if (/^.*ESSID\:\"([a-zA-Z0-9]*)\"/) {
$essid = $1;
}
if (/^.*ESSID\:off/) {
$essid = "";
}
if (/(..:..:..:..:..:..)/) {
if (!$essid) { $essid="";}
$accesspoint->set_text("$essid ($1)");
$actual_mac=$1;
}
if (/^.*Access\ Point\: 00\:00\:00/) {
$accesspoint->set_text("$essid");
$actual_mac="";
}
if (/^.*Bit\ Rate:(.*)/) {
$bitrate = $1;
}
if (/Signal:(.*)/) {
$senal->set_text("$1");
}
if (/^.*Quality.(.*).*Signal\ level.(.*)/) {
if (!$bitrate) { $bitrate="";}
$velocidad->set_text("$bitrate");
$calidad->set_text("$1");
$senal->set_text("$2");
}
}
} # end guifi_estado_wifi
sub guifi_estado_IP {
my $iface = guifi_interface();
# Execute ifconfig
$command="ifconfig $iface";
my ($bitrate,$essid);
my $estado="Interfaz Desactivada (DOWN)";
foreach (`$command`)
{
if (/^.*inet\ addr\:(.*)\ Bcast.*Mask\:(.*)/) {
$dirIP->set_text("$1/$2");
}
if (/UP\ /) {
$estado = "ACTIVA";
}
if (/^.*\((.*)\).*\((.*)\)/) {
$txrx->set_text("$2 / $1");
}
}
$if_estado->set_text("$estado");
# Check DNS configuration
my $dnsconfig=`grep -i nameserver /etc/resolv.conf | sed s/nameserver//g`;
chomp($dnsconfig);
$dns->set_text($dnsconfig);
my $router=`route -n | grep ^0.0.0.0 | awk {'print \$2'}`;
chomp($router);
$gateway->set_text($router);
} # end guifi_estado_IP
sub apply_config
{
my $iface = guifi_interface();
my $command="iwconfig $iface ";
if ($myessid->get_text) { $command = $command." essid ".$myessid->get_text." " ;}
# Configure WEP keys
if ($WEP1->get_text) {
$command = $command." key 1 ".$WEP1->get_text;
if ($WEP2->get_text) { $command = $command." key 2 ".$WEP2->get_text; }
if ($WEP3->get_text) { $command = $command." key 3 ".$WEP3->get_text; }
if ($WEP4->get_text) { $command = $command." key 4 ".$WEP4->get_text; }
`$command`;
}
else
{
$command = $command." key off";
}
# Configure Channel
if ($canal->get_text) {
$command = $command." channel ".$canal->get_text;
}
# Execute iwconfig command
print "Executing: $command \n";
`$command`;
# IP Configuration
if ($manual_ip->get_text) {
$command = "ifconfig $iface ".$manual_ip->get_text." netmask ".$manual_subnet->get_text;
print "Executing: $command \n";
`$command`;
# Remove default route
$command = "route del -net default";
print "Executing: $command \n";
`$command`;
# Create default route
$command = "route add -net default gw ".$manual_gw->get_text;
print "Executing: $command \n";
`$command`;
$command = "echo nameserver ".$manual_dns->get_text." > /etc/resolv.conf";
print "Executing: $command \n";
`$command`;
}
} # end apply_config
sub grabar_config
{
$indice=join(", ", $slist->get_selected_indices);
my $mac=$slist->{data}[$indice][7];
$cfg->set("$mac.myessid",$myessid->get_text);
$cfg->set("$mac.auto",$automatico->get_active);
$cfg->set("$mac.wep1",$WEP1->get_text);
$cfg->set("$mac.wep2",$WEP2->get_text);
$cfg->set("$mac.wep3",$WEP3->get_text);
$cfg->set("$mac.wep4",$WEP4->get_text);
$cfg->set("$mac.channel",$canal->get_text);
$cfg->set("$mac.ip",$manual_ip->get_text);
$cfg->set("$mac.mask",$manual_subnet->get_text);
$cfg->set("$mac.gw",$manual_gw->get_text);
$cfg->set("$mac.dns",$manual_dns->get_text);
$cfg->save_config();
} # end grabar_config
sub read_config
{
$indice=join(", ", $slist->get_selected_indices);
my $mac=$slist->{data}[$indice][7];
if ($cfg->{"$mac.myessid"}) {
$myessid->set_text($cfg->{"$mac.myessid"}); }
else {
$myessid->set_text($cfg->{"$mac.essid"}); }
$automatico->set_active($cfg->{"$mac.auto"});
$WEP1->set_text($cfg->{"$mac.wep1"});
$WEP2->set_text($cfg->{"$mac.wep2"});
$WEP3->set_text($cfg->{"$mac.wep3"});
$WEP4->set_text($cfg->{"$mac.wep4"});
$canal->set_text($cfg->{"$mac.channel"});
$manual_ip->set_text($cfg->{"$mac.ip"});
$manual_subnet->set_text($cfg->{"$mac.mask"});
$manual_gw->set_text($cfg->{"$mac.gw"});
$manual_dns->set_text($cfg->{"$mac.dns"});
} # end read_config
sub CheckAutoconnect {
@lista=$slist->{data};
for (my $number = 0; $number <=99; $number++) {
$essidmac=$lista[0][$number][7];
if (!$essidmac) { $number=999;}
else {
print $essidmac." $number \n";
$slist->select($number);
# AUTO-CONNECT
if ($automatico->get_active=="1") {
AutoConectar();
my $alerta = Gtk2::Dialog->new( 'Conexión Automática', undef, 'modal',
'gtk-quit' => 'ok','gtk-cancel' => 'cancel' );
my $text ="Se ha conectado automáticamente a ".$myessid->get_text;
$alerta->vbox->pack_start( Gtk2::Label->new( $text ), FALSE, FALSE,4 );
$alerta->vbox->show_all;
$respuesta=$alerta->run;
if ('ok' eq $respuesta) { exit; }
if ('cancel' eq $respuesta) { $alerta->destroy;}
}
}
}
}
################################################################
#
# BEGIN CONFIGURATION MANAGEMENT MODULE
#
################################################################
package ManageConfig;
sub new {
my ($class_name) = @_;
my ($self) = {};
bless ($self, $class_name);
$self->{'_guifi'} = 1;
return $self;
}
sub read_config {
my ($self, $file) = @_;
my ($line, $section);
open (CONFIGFILE, $file) or return 0;
$self->{'_filename'} = $file;
while ($line = <CONFIGFILE>) {
if ($line =~ /^\[(.*)\]/) {
$section = $1;
} elsif ($line =~ /^([^=]+)=(.*)/) {
my ($config_name, $config_val) = ($1, $2);
if ($section) {
$self->{"$section.$config_name"} = $config_val;
} else {
$self->{$config_name} = $config_val;
}
}
}
close CONFIGFILE;
return 1;
}
sub get {
my ($self, $key) = @_;
return $self->{$key};
}
sub set {
my ($self, $key, $value) = @_;
$self->{$key} = $value;
}
sub save_config {
my $self = shift;
my @keys = @_ ? @_ : sort keys %$self;
open (RCFILE, ">".$self->{"_filename"});
my $prev_titulo="";
foreach $key (@keys) {
$_=$key;
if (!/^_/) {
if ($key =~ /^(.*)\.(.*)/) {
$titulo=$1;
$variable=$2;
if ($prev_titulo ne $titulo) {
print RCFILE "[$titulo]\n";
$prev_titulo = $titulo;
}
$valor=$self->{$key};
print RCFILE "$variable=$valor\n";
}
}
}
close (RCFILE);
}
1;