2007-01-24, 13:01
  #1
Medlem
acuras avatar
Här är ett program som jag anväder mig av för att lättare ansluta till trådlösa nätverk i linux. Det är textbaserat så det ska rulla på fint på alla datorer.

Kod:
#!/usr/bin/perl 
#PiFi version 0.31 released under GNU GPL2 
#This is Perl program written to make it more simple to connect 
#to the most common WiFi nets (open, WEP and WPA-PSK). 
#It uses wirelesstools to scan and connect to WiFi nets. 
#To be able to connect to WPA-PSK encrypted nets wpa_supplicant is 
#a dependency. 
# 
#This program is written by Rickard Gustafson (rickard.gustafson@gmail.com 
Citera
2007-01-24, 13:02
  #2
Medlem
acuras avatar
Kod:
use strict; 
use Math::BigInt; 
use Getopt::Long qw(:config pass_through); 

use vars qw($VERSION); 
$VERSION = 0.31; 

sub version { 
    print "PiFi version $VERSION\n"; 
} 

#Check if valid wifi-inteface. 
sub valid_if { 
    my ($if) = @_; 
    system("ifconfig $if up"); 
    $_ = `iwconfig $if 2>&1`; # 2>&1 redirect STDERR to STDOUT 
    return /ESSID/; 
} 

#Checks ip wpa_supplicant exists in path. 
sub check_wpa { 
    $_ = `which wpa_supplicant`; 
    return !/which/; 
} 

#Scan and parse SSIDs. 
sub scan_ssid { 
    my ($if) = @_; 
    my @lines = `iwlist $if scan`; 
    my @nets = (); 
    my @ssid = (); 
    my $i = 0; 

    for (0..$#lines) { 
        if (@lines[$_] =~ s/.*ESSID:"(.*)"/$1/) { #Get ssid and stores in first cell of vector. 
            chomp @lines[$_]; 
            @ssid[0] = @lines[$_]; 
            $i++; 
        } 
        if (@lines[$_] =~ s/.*key:(.*)/$1/) { #Gets encryption, if WPA it extends vector with chipper 
            $i++; 
            my $j; 
            if (@lines[$_] =~ /on/) { 
                @ssid[2] = 1; #Field 2 is a boolean for encryption 
                if (@lines[$_+5] =~ /WPA/) { 
                    @lines[$_+5] =~ s/.*IE: (.*) Version.*/$1/; #@lines[$_+5] =~ s/.*IE: (.*) Version (.)/$1$2/; does the same but also stores wpa version. 
                    chomp @lines[$_+5]; 
                    @ssid[3] = @lines[$_+5]; 
                    for $j (4..6) {  #Gets chippers and other extra output from iwlist. 
                        @lines[$_+$j+2] =~ s/.*: (.*)/$1/; 
                        chomp @lines[$_+$j+2]; 
                        @ssid[$j] = @lines[$_+$j+2]; 
                    } 
                } 
                else { 
                    @ssid[3] = "WEP"; 
                    for $j (4..6) { #These fields are obsolete for WEP but set to zero to not get any missmatching. 
                        @ssid[$j] = 0; 
                    } 
                } 
            } 
            else { 
                @ssid[2]= 0; 
                for $j (2..6) {#These fields are obsolete but set to zero to not get any missmatching. 
                    @ssid[$j] = 0; 
                } 
            } 
        } 
        if (@lines[$_] =~ s/.*=(.*)\/(.*)/$1/) { #Signalstrength 
            chomp @lines[$_]; 
            @ssid[1] = @lines[$_]; 
            $i++; 
        } 
        if ($i == 3) { 
            push @nets, [@ssid]; 
            $i = 0; 
        } 
    } 
    return @nets; 
} 

#Returns encryption type from array like an integer. Returns 0 for none, 1 for WEP and 2 for WPA. 
sub enc_type { #enc_type(@net) 
    my (@net) = @_; 
    if (@net[2] == 0) { 
        return 0; 
    } 
    if (@net[2] == 1 && @net[3] =~ /WEP/) { 
        return 1; 
    } 
    if (@net[2] == 1 && @net[3] =~ /WPA/) { 
        return 2; 
    } 
} 

#Print ssid and info from given vector. 
sub print_ssid { 
    my @nets = @_; 
    my $i; 

    die ("No networks found.") unless ($#nets != -1); 

    for $i (0..$#nets) { 
        my $sig = Math::BigInt -> new($nets[$i][1]); 
        my $stars = "#" x ($sig / 2); 
        my $enc = ($nets[$i][2] == 0) ? "not encypted." : "encrypted with $nets[$i][3]"; 
        printf("Network id: %d\n", $i+1); 
        print "SSID: $nets[$i][0]\n"; 
        printf("This network is %s\n", $enc); 
        printf("Link quality: [%-50s %3d\%]\n", $stars, $sig ); 
        print "-" x 70 . "\n"; 
    } 
    return 0; 
} 

#Generates configuration file for wpa_supplicant. 
sub gen_conf { # gen_conf($ssid, $secret, $file) 
    my ($ssid, $secret, $file) = @_; 
    $_ = `wpa_passphrase $ssid "$secret"`; 
    my @wpa = split /\n/; 
    open(FILE,">$file"); 
    print FILE "ctrl_interface=/var/run/wpa_supplicant\n"; 
    print FILE "ctrl_interface_group=0\n"; 
    print FILE "eapol_version=1\n"; 
    print FILE "ap_scan=1\n"; 
    print FILE "fast_reauth=1\n"; 
    print FILE "\n\n\nnetwork={\n"; 
    #WPA 
    print FILE "scan_ssid=1\n"; 
    print FILE "ssid=\"$ssid\"\n"; 
    print FILE "proto=WPA\n"; 
    print FILE "key_mgmt=WPA-PSK\n"; 
    print FILE "pairwise=CCMP TKIP\n"; 
    print FILE "group=CCMP TKIP WEP104 WEP40\n"; 
    print FILE "@wpa[3]\n"; 
    print FILE "}\n"; 
    close(FILE); 
    return 0; 
} 

#Connects to wpa encrypted network with given interface, SSID and PSK. 
sub wpa_connect { #wpa_connect($iw, $ssid, $secret) 
    my ($iw, $ssid, $secret) = @_; 
    my $file = "/tmp/wpa_supplicant.conf"; 
    gen_conf($ssid, $secret, $file); 
    system("wpa_supplicant -Dwext -i$iw -c$file -B"); #wext is a chipper wpa_supplicant allways is compiled with and probably all drivers works with. 
    unlink($file); 
    return 0; 
} 

#Connects to wep encrypted network with ginev interface, SSID and hex-key. 
sub wep_connect { #wep_connect($iw, $ssid, $key) 
    my ($iw, $ssid, $key) = @_; 
    system("iwconfig $iw mode managed key $key"); 
    system("iwconfig essid $ssid"); 
    return 0; 
} 

#Connects to open network with given interface and SSID 
sub open_connect { #open_connect($iw, $ssid) 
    my ($iw, $ssid) = @_; 
    system("iwconfig $iw essid $ssid"); 
    return 0; 
} 

#Escapes quotes in string. 
sub quote_escape { 
    $_ = @_; 
    s/\"/\\\"/g; 
    return; 
} 

#Set IP on given interface with given client. 
sub ip_dhcp { #ip_dhcp($iw, $client) 
    my ($iw, $client) = @_; 
    system($client $iw); 
    return 0; 
} 

#Set IP on given interface with ifconfig and given ip-string. 
sub ip_static { #ip_static($iw, $ip) 
    my ($iw, $ip) = @_; 
    system("ifconfig $iw $ip"); 
    return 0; 
} 

#Function for running as wizard. 
sub wizard { 
    #Get which interface and checks if valid. 
    print "Enter which interface you want to connect with (eg. ath0 eth1 wifi0): "; 
    my $iw = <STDIN>; 
    chomp $iw; 
    die ("\n$iw does not seem to be a valid WiFi interface please check your spelling.\n") unless ( valid_if($iw) == 1); 
    
    #Scan and print aviable networks. 
    my @nets = scan_ssid($iw); 
    print_ssid(@nets); 

    #Get network id. 
    print "\nEnter id of SSID you want to connect: "; 
    my $id = <STDIN>; 
    chomp $id; 
    $id--; 
    die ("You want to connect to a WPA encrypted network and wpa_supplicant does not exists in path.\n") 
        if (enc_type(@{$nets[$id]}) == 2 && check_wpa == 0); 
    
    #Connect to AP. 
    if (enc_type(@{$nets[$id]}) == 0) { 
        open_connect($iw, $nets[$id][0]); 
    } 
    if (enc_type(@{$nets[$id]}) == 1) { 
        print "\nEnter WEP-key: "; 
        my $key = <STDIN>; 
        chomp $key; 
        wep_connect($iw, $nets[$id][0], $key); 
    } 
    if (enc_type(@{$nets[$id]}) == 2) { 
        print "\nEnter WPA-passphrase: "; 
        my $psk = <STDIN>; 
        chomp $psk; 
        $psk = quote_escape($psk); 
        wpa_connect($iw, $nets[$id][0], $psk); 
    } 

    #IP configuration. 
    print "\nTo use DHCP enter your client below.\n"; 
    print "To use static IP enter an ifconfig compatible string.\n"; 
    print "Example: 10.0.0.1, 10.0.0.1 netmask 255.255.255.0, 10.0.0.1 netmask 0xffffff00, 10.0.0.1/24\n"; 
    print "wifi> "; 
    my $adr = <STDIN>; 
    chomp $adr; 
    if ($adr =~ /[dD][hH][cC]/) { 
        ip_dhcp($iw, $adr); 
    } 
    else { 
        ip_static($iw, $adr); 
    } 
} 

#Main function. Parses arguments. 
sub main { 
    my ($wizard,@open, @wep, @wpa, $help, $version); 
    GetOptions ('w|wizard' => \$wizard, 
                'o|open=s{2}' => \@open, 
                'wep=s{3}' => \@wep, 
                'wpa=s{3}' => \@wpa, 
                'h|help' => \$help, 
                'v|version' => \$version); 
    if ($#ARGV != -1) { 
        die ("Try -h --help for usage.\n"); 
    } 
        
    if ((@open && (@wep || @wpa)) || (@wep && @wpa)) { 
        die ("Option open, wep and wpa obsoletes each other. Do not try to combine them!\n") 
    } 

    #Connect to open network. 
    #Helptext: -o --open [inteface ssid] 
    if ($#open != -1) { 
        #valid_if(@ARGV[0]) || die ("Not a valid WiFi interface."); #Seems to be obsolet 
        die ("To few arguments\n") unless ($#open == 1); 
        open_connect(@open); 
    } 

    #Connect to WEP network. 
    #Helptext: --wep [interface ssid key] 

    elsif ($#wep != -1) { 
        #valid_if(@ARGV[0]) || die ("Not a valid WiFi interface."); #Seems to be obsolet 
        die ("To few arguments\n") unless ($#wep == 2); 
        wep_connect(@wep); 
    } 
    #Connect to WPA-PSK. 
    #Helptext: --wpa [interface ssid passphrase] 
    elsif ($#wpa != -1) { 
        #valid_if(@ARGV[0]) || die ("Not a valid WiFi interface."); #Seems to be obsolet 
        die ("To few arguments\n") unless ($#wpa == 2); 
        wpa_connect(@wpa); 
    } 

    #Start PiFi in wizard mode. 
    elsif ($wizard == 1) { 
        wizard(); 
    } 
    #Help. 
    elsif ($help == 1) { 
        print "PiFi usage:\n"; 
        print "-w --wizard\t\t\t\tWizard mode, similar as no option.\n"; 
        print "-o --open [inteface ssid]\t\tConnect to open network\n"; 
        print "--wep [interface ssid key]\t\tConnect to WEP encrypted network.\n"; 
        print "--wpa [interface ssid passphrase]\tConnect to WPA-PSK encrypted network.\n"; 
        print "-v --version\t\t\t\tPrint version.\n"; 
        print "-h --help\t\t\t\tPrint this helpmessage.\n"; 
    } 
    #Version. 
    elsif ($version == 1) { 
        version(); 
    } 
    #If no arguments are passed start as wizard. 
    else { 
        wizard(); 
    } 
} 

main();
Citera
2007-01-24, 14:02
  #3
Medlem
Dr.Kratzs avatar
Fint gjort. Såg det på bbs.linux.se. Jag skall testa det någon gång när jag skall koppla upp mig mot ett WPA nät. Vilket som känt är relativt omständigt!
Citera
2007-01-25, 22:08
  #4
Medlem
Vad kan det här tänkas betyda?
Kod:
nilsl@***:~/projects/perl$ perl wlan.pl
Error in option spec: "o|open=s{2}"
Error in option spec: "wep=s{3}"
Error in option spec: "wpa=s{3}"
Citera
2007-01-26, 20:44
  #5
Medlem
acuras avatar
Citat:
Ursprungligen postat av nilsL
Vad kan det här tänkas betyda?
Kod:
nilsl@***:~/projects/perl$ perl wlan.pl
Error in option spec: "o|open=s{2}"
Error in option spec: "wep=s{3}"
Error in option spec: "wpa=s{3}"

Det är i main Getoptions som det blir något fel för dig. Vilken version av perl använder du? jag använder Perl v5.8.8 och då fungerar det bra för mig. En sak du skulle kunna prova att göra är att är att ta bort hela funktionen main och byta ut main(); mot wizard(); på sista raden.
Citera
2007-04-08, 00:12
  #6
Medlem
acuras avatar
Det har kommit fram att outputen från iwlist skiljer sig i vissa distributioner från de jag testat med (Archlinux, Gentoo och Slackware). En lösning på detta är att ändra lite i raden som innehåller '#Signalstrength' (rad 79 bör det nog vara) till:
Kod:
if (@lines[$_] =~ s/.*=(.*)\/(.*)/$1/ || @lines[$_] =~ s/^Quality:(\d+)/$1/) { #Signalstrength
Citera

Skapa ett konto eller logga in för att kommentera

Du måste vara medlem för att kunna kommentera

Skapa ett konto

Det är enkelt att registrera ett nytt konto

Bli medlem

Logga in

Har du redan ett konto? Logga in här

Logga in