#!/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 = ) { 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;