#!/usr/bin/perl use strict; use Term::ReadKey; my $interface = "ath0"; my $madwifing="wifi0"; #leave blank for non madwifi card. Otherwise, set to base driver. AKA wifi0. #my $interface = "eth1"; #my $madwifing=""; #leave blank for non madwifi card. Otherwise, set to base driver. AKA wifi0. #wep keys my %key_list; $key_list{'linksys1'} = '1A2345F64'; my $scan_a_lot = 0; #set this to scan every screen refresh when not associated. #Some cards will locked if you run iwlist too much. With this set to 0, it will only scan after pressing enter. #When associated, it will never scan except when pressing enter as the scanning can knock off the connection for a few seconds #depending on the card. Atheros with madwifi can do it all day and only loose a few packets. My Zyxel can take 3 seconds. ##############################################################3 #Version 0.3 #Added essid/mac toggle.(bug: does not wait for connection in mac mode. I can't figure out how to tell it's connected) #Fixed to show AP with blank names #Version 0.2 #Added Madwifi Support #Added adhoc support #Version 0.1 Initial Version ############################################################################ my @ap_list; my $essidormac = "essid"; my $current_ip; my $current_essid; my $current_mac; my $current_quality; my $random_mac; `ifconfig $interface down`; `ifconfig $interface up`; my $clear = `clear`; ReadMode 3; # Turn off controls keys #&ap_scan; #scan for anything new &ap_list; exit; format STDOUT_TOP = NUM: ESSID: MAC: QTY: CHN: ENC: MODE: . ############################################################ sub ap_list() { my $input; my $key; my ($ap_number2,$ap_essid2,$ap_mac2,$ap_quality2,$ap_channel2,$ap_enc2,$ap_mode2); #main waiting loop until (0) { #while (not defined ($key = ReadKey(-1))) { #get info about our current connection &client_connect; #don't scan if we are connected to anything. Can cause a problem on some wifi cards. if ($current_mac =~ /-/ && $scan_a_lot) { &ap_scan; #scan for anything new } print $clear; print "Total AP Found: ".($#ap_list + 1) . "|". time . "|$current_ip|$current_essid|$current_mac|$current_quality \n"; $- = 0; # Force the print of the new header format STDOUT = @<< @<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<< @<<< @<< @<<< @<<<<<<< $ap_number2,$ap_essid2,$ap_mac2,$ap_quality2,$ap_channel2,$ap_enc2,$ap_mode2 . for (my $b=0;$b<=$#ap_list;$b++){ ($ap_number2,$ap_essid2,$ap_mac2,$ap_quality2,$ap_channel2,$ap_enc2,$ap_mode2) = split(/\t/, @ap_list[$b]); write STDOUT; }; print "\n\nToggles:\n"; print "r: Random Mac:\n"; print "k: Keep Connection:\n"; print "a: Associate by essid or mac: $essidormac\n"; print "\nCommands:\n"; print "1-x: Connect to X numbered AP\n"; print "q: Quit, leave network up\n"; print "s: Shut down, shutdown the network\n"; print "f: Free Wifi. Try to connect to anything that will let us and get internet access.\n"; print " to refresh the list\n"; #This is the sleep/pause section. #It loops every half second looking for a key press. #If it finds one, it bails. If not, it still bails after 5 seconds to update the screen. my $d=0; while (not defined ($key = ReadKey(-1))) { if ($d > 10){last;} select(undef,undef,undef,(0.5)); $d++; } # No key yet #} if ($key =~ /\d/) {&connect_now($key);}; if ($key eq "q") {ReadMode 0; exit;}; if ($key eq "f") {&free_wifi;}; if ($key eq "s") {&die_now;}; if ($key eq "\n") {&ap_scan;}; #Scan on enter key press' if ($key eq "a") { if ($essidormac eq "essid") {$essidormac = "mac";} else {$essidormac = "essid";};}; #print "Get key $key\n"; }; }; #end sub ap_list ###################################################### sub check_internet() { }; ######################################################### sub die_now() { #shutdown the wireless interface then shut down. `iwconfig $interface essid none`; `ifconfig $interface down`; ReadMode 0; exit; }; #sub die_now; ####################################################### sub connect_now() { #connect to the AP my $ap; #if we have more then 10 ap, then wait for a second key #If we have more then 99, dang. if ($#ap_list > 9) { #print "more then 10 found, type another digits\n\n"; my $key; my $firstdig = $_[0]; print $firstdig; while (not defined ($key = ReadKey(-1))) { if ($key =~ /\d/){last;} select(undef,undef,undef,(0.5)); } print $key; $ap = ($firstdig.$key); } else { $ap = $_[0]; }; my $key = "key off"; my $mode; my ($ap_number2,$ap_essid2,$ap_mac2,$ap_quality2,$ap_channel2,$ap_enc2,$ap_mode2) = split(/\t/, @ap_list[$ap]); print "\n\n$ap_number2,$ap_essid2\n\n"; if (! $ap_mac2) {return;}; #hit the wrong thing, so do nothing. #check wep key if ($key_list{$ap_essid2}) { $key = "key ".$key_list{$ap_essid2};}; my $essid = $ap_essid2; if (! $madwifing) { if($ap_mode2 eq "Ad-Hoc") { `iwconfig $interface mode Ad-Hoc`;} if($ap_mode2 eq "Master") { `iwconfig $interface mode Managed`;} } else { #`wlanconfig $interface destroy`; #if($ap_mode2 eq "Ad-Hoc") { `wlanconfig $interface create wlandev $madwifing wlanmode adhoc`;} #if($ap_mode2 eq "Master") { `wlanconfig $interface create wlandev $madwifing wlanmode sta`;} } #kick the wireless card in the pants. It seems to help. `ifconfig $interface down`; `ifconfig $interface up`; if ($essidormac eq "essid") { `iwconfig $interface essid "$essid" $key`; #connect by essid } else { `iwconfig $interface essid any $key ap '$ap_mac2'`; #connect by mac }; $current_mac=""; #loop until we connect to the ap #print time; my $c = 0; until ($current_mac =~ /:/) { print $clear; print "Waiting to connect to $essid $key for $c \n\n"; print &client_connect; if ($c == 30) {last;} #give up after 30 seconds $c++; sleep 1; } if ($current_mac =~ /:/) { #we connected, good. Now run dhclient `ifconfig $interface 200.200.200.200`; #no way exist to check of dhclient sucessed, so we assign a fake address and see if dhclient changes it. `killall dhclient`; `dhclient $interface`; sleep 5; }; }; #end sub connect_now #################################################### sub free_wifi() { #This sub attempts to get free wifi. #1) Goes down the list of AP found. #2) If AP has encryption, check to see if we have a key, if we don't, then skip it. #3) Attempt to connect to the AP, if we don't, skip this AP. #4) Attempt DHCP to get an ip address, if not, skip this AP. #5) Attempt a ping to google.com, if we can't ping, skip this AP. #If we get to this point, we are connected. Surf away. for (my $b=0;$b<=$#ap_list;$b++){ my ($ap_number2,$ap_essid2,$ap_mac2,$ap_quality2,$ap_channel2,$ap_enc2,$ap_mode2) = split(/\t/, @ap_list[$b]); #If the ap has encryption on, and we don't have a key for it, then don't bother trying to connect. if ($ap_enc2 eq "on" && ! $key_list{$ap_essid2}) {next;} #Only try connecting to real AP. None of the adhoc stuff as it's not likly to work. if ($ap_mode2 ne "Master") {next;} #connect to the ap. and get a dhcp address. &connect_now($b); &client_connect(); if ($current_mac =~ /-/) {next;} #skip if we are not connected #if we got an address, try a ping. if ($current_ip ne "200.200.200.200") { print "Checking for Internet access\n"; my $ping = `ping -c 3 google.com`; print $ping; print "Checking Ping"; if ($ping =~ /from/) { #print $clear; print "\n\n**************Internet Found*******************\n\n"; sleep 5; last; #get out of the loop. } } print "No internet found, trying next ap\n"; }; }; #end free_wifi sub #################################################### #Update the information on who we are connected to sub client_connect() { $current_ip = ""; $current_essid = ""; $current_mac = ""; my $iw_info=`iwconfig $interface`; my $if_info=`ifconfig $interface`; #Get the Essid we are connected to. $iw_info =~ /ESSID:(.*)\s\s\n/; $current_essid = $1; #Get the Essid we are connected to. $iw_info =~ /Point: (.*)\s\s\s\n/; $iw_info =~ /Cell: (.*)\s\s\s\n/; $current_mac = $1; my $blank =~ /()/; #Get the Essid we are connected to. $if_info =~ /addr:(\d*\.\d*\.\d*\.\d*)/; $current_ip = $1; #Quality $iw_info =~ /Quality=(\d*)/; $current_quality = $1; #print $1; #exit; return $iw_info; }; #end sub client connect ################################################# ###################################################### #scan for a list of ap and load them into the array. sub ap_scan() { @ap_list =(); #clear out the array for new list my ($ap_number,$ap_essid,$ap_mac,$ap_quality,$ap_channel,$ap_enc,$ap_mode); my $ap_list=`iwlist $interface scan`; my @ap_each=split(/Cell/,$ap_list); my $each; my $a=0; foreach $each (@ap_each) { #print "----New-----\n"; #Mac address $each =~ /Address: (.*)\n/; if (! $1) {next;} #if we didn't get an essid, then skip this loop. $ap_mac = $1; $ap_number = $a; #ESSID $each =~ /ESSID:\"(.*)\"\n/; $ap_essid = $1; #counter #Mode $each =~ /Mode:(.*)\n/; $ap_mode = $1; #Channel $each =~ /Channel (.*)\)\n/; $ap_channel = $1; #Quality $each =~ /Quality[:|=](\d*)/; $ap_quality = $1; #Encrypton key $each =~ /key:(.*)\n/; $ap_enc = $1; ##print $1 ."\n"; $a++; push(@ap_list, "$ap_number\t$ap_essid\t$ap_mac\t$ap_quality\t$ap_channel\t$ap_enc\t$ap_mode"); } }; #end sub ap_scan