Gentoo's baselayout tends to not work so well for wireless, and it only tries each SSID once before skipping to the next, regardless of multiple APs. Because of this, I decided to write my own script which runs dhclient, iwlist, iwconfig, and ifconfig to set the interface up. This script is a bit limited and rough since the MAC address stuff isn't actually used, and the preferred SSIDs are defined in the file (as are the MAC addresses).
netz.pl
#!/usr/bin/perl -w
use strict;
use warnings;
scalar @ARGV || die "Usage: $0 iface [ MACmode ]\n";
my $iface = shift @ARGV;
my %macs = ('default' => '00:00:00:00:00:00', 'alt1' => '00:00:00:00:00:00');
my $mac = $macs{default};
scalar @ARGV && ($mac = $macs{$ARGV[0]});
system("ifconfig $iface up");# || die "No such interface: $iface\n";
open(IWCONFIG, "iwlist $iface scanning|") || die "Unable to find iwlist.\n";
my @lines = <IWCONFIG>;
chomp(@lines);
close(IWCONFIG);
scalar @lines || die "No wireless extensions on $iface\n";
system('killall dhclient');
my %aps;
my @tline = ();
our @preferred = ('UniversityOfWashingtonCSE', 'EE', 'University of Washington');
foreach(@lines) {
if(/^\s+Cell [0-9][0-9] - Address: [0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}/) {
if(scalar @tline) {
my %tap = &newap(@tline);
my $tqual = &zerolead(2, $tap{quality});
if($aps{$tap{quality}}) {
push(@{$aps{$tqual}}, \%tap);
}
else {
$aps{$tqual} = [\%tap];
}
@tline = ();
}
push(@tline, $_);
}
elsif(/ESSID:"[^"]+"/ || /Mode:[A-Za-z]+/ || /Frequency:[0-9.]+\s.Hz \(Channel [0-9]+\)/ || /Quality=[0-9]+\/70/) {
push(@tline, $_);
}
}
my @picked;
my @keys = reverse sort keys %aps;
my $found = 0;
for(my $i = 0; $i < scalar @keys; $i++) {
my @sublist = @{$aps{$keys[$i]}};
for(my $q = 0; $q < scalar @sublist; $q++) {
my %ap = %{$sublist[$q]};
(push(@picked, \%ap)) and ($found = 1) if(&arrayfind($ap{ssid}, @preferred) >= 0);
}
}
$found || die "Unable to choose access point for $iface\n";
$found = 0;
for(my $i = 0; !$found && $i < scalar @picked; $i++) {
$found = 0;
my %chosen = %{$picked[$i]};
print "$chosen{ssid} : $chosen{ap} {\n\tQuality: $chosen{quality}/70\n\tChannel: $chosen{channel}\n\tMode: $chosen{mode}\n}\n\n";
system("iwconfig $iface ap $chosen{ap} essid \"$chosen{ssid}\"");
open(DHCP, "dhclient $iface 2>&1 |") || die "Unable to find dhclient.\n";
@lines = <DHCP>;
close(DHCP);
(scalar grep(/No DHCPOFFERS received\./, @lines) && print "Unable to get DHCP lease on $iface.\n\n") || ($found = 1);
if($found) {
open(NSLOOKUP, "nslookup -timeout=5 google.com|");
@lines = <NSLOOKUP>;
close(NSLOOKUP);
(scalar grep(/connection timed out/i, @lines) || scalar grep(/NXDOMAIN/, @lines)) && (print "Unable to find google.com via DNS over $iface.\n") && ($found = 0);
}
}
$found || die "Unable to get connection on $iface\n";
sub zerolead {
my $len = shift;
my $str = shift;
($str = '0' . $str) while(length($str) < $len);
return $str;
}
sub newap {
my @text = @_;
my %self = ('standard' => '', 'ssid' => '', 'mode' => '', 'frequency' => '', 'ap' => '', 'quality' => '', 'channel' => '');
foreach(@text) {
if(/^\s+Cell [0-9][0-9] - Address: ([0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2})/) {
$self{ap} = $1;
}
elsif(/ESSID:"([^"]+)"/) {
$self{ssid} = $1;
}
elsif(/Mode:([A-Za-z-]+)/) {
$self{mode} = $1;
}
elsif(/Frequency:([0-9.]+\s.Hz) \(Channel ([0-9]+)\)/) {
($self{frequency}, $self{channel}) = ($1, $2);
}
elsif(/Quality=([0-9]+)\/70/) {
$self{quality} = $1;
}
}
return %self;
}
sub arrayfind {
my $term = shift;
my @find = @_;
for(my $i = 0; $i < scalar @find; $i++) {
return $i if($term eq $find[$i]);
}
return -1;
}
No comments:
Post a Comment