summaryrefslogtreecommitdiffstats
path: root/lib/network/monitor.pm
blob: c0ed8f80e0a7fbf5cbd34d3b54c1975d676be402 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package network::monitor;

use common;
use dbus_object;

our @ISA = qw(dbus_object);

sub new {
    my ($type, $bus) = @_;
    dbus_object::new($type,
		       $bus,
		       "com.mandriva.monitoring",
		       "/com/mandriva/monitoring/wireless",
		       "com.mandriva.monitoring.wireless");
}

sub list_wireless {
    my ($monitor, $o_intf) = @_;
    my ($results, $list, %networks);
    #- first try to use mandi
    eval {
        $results = $monitor->call_method('ScanResults');
        $list = $monitor->call_method('ListNetworks');
    };
    my $has_roaming = defined $results && defined $list;
    #- try wpa_cli if we're root
    if ($@ && !$>) {
        $results = `/usr/sbin/wpa_cli scan_results 2>/dev/null`;
        $list = `/usr/sbin/wpa_cli list_networks 2>/dev/null`;
    }
    if ($results && $list) {
        #- bssid / frequency / signal level / flags / ssid
        while ($results =~ /^((?:[0-9a-f]{2}:){5}[0-9a-f]{2})\t(\d+)\t(\d+)\t(.*?)\t(.*)$/mg) {
            #- wpa_supplicant may list the network two times, use ||=
            $networks{$1}{frequency} ||= $2;
            #- signal level is really too high in wpa_supplicant
            #- this should be standardized at some point
            $networks{$1}{signal_level} ||= int($3/3.5);
            $networks{$1}{flags} ||= $4;
            $networks{$1}{essid} ||= $5 if $5 ne '<hidden>';
        }
        #- network id / ssid / bssid / flags
        while ($list =~ /^(\d+)\t(.*?)\t(.*?)\t(.*)$/mg) {
            if (my $net = $networks{$3} || find { $_->{essid} eq $2 } values(%networks)) {
                $net->{id} = $1;
                $net->{essid} ||= $2;
                $net->{current} = to_bool($4 eq '[CURRENT]');
            }
        }
    } elsif ($o_intf) {
        #- else use iwlist
        my $current_essid = chomp_(`/sbin/iwgetid -r $o_intf`);
        my $current_ap = lc(chomp_(`/sbin/iwgetid -r -a $o_intf`));
        my @list = `/sbin/iwlist $o_intf scanning`;
        my $net = {};
	foreach (@list) {
            if ((/^\s*$/ || /Cell/) && exists $net->{ap}) {
                $net->{current} = to_bool($net->{essid} && $net->{essid} eq $current_essid || $net->{ap} eq $current_ap);
                $networks{$net->{ap}} = $net;
                $net = {};
            }
            /Address: (.*)/ and $net->{ap} = lc($1);
            /ESSID:"(.*?)"/ and $net->{essid} = $1;
            /Mode:(\S*)/ and $net->{mode} = $1;
            if (m!Quality[:=](\S*)/!) {
                my $qual = $1;
                $net->{signal_level} = $qual =~ m!/! ? eval($qual)*100 : $qual;
            }
            /Extra:wpa_ie=/ and $net->{flags} = '[WPA]';
            /key:(\S*)\s/ and $net->{flags} ||= $1 eq 'on' && '[WEP]';
	}
    }

    $networks{$_}{approx_level} = 20 + min(80, int($networks{$_}{signal_level}/20)*20) foreach keys %networks;
    (\%networks, $has_roaming);
}

sub select_network {
    my ($o, $id) = @_;
    $o->call_method('SelectNetwork', Net::DBus::dbus_uint32($id));
}

1;