File Coverage

blib/lib/Net/Wireless/802_11/Scan/FreeBSD.pm
Criterion Covered Total %
statement 14 113 12.3
branch 0 38 0.0
condition n/a
subroutine 5 9 55.5
pod 4 4 100.0
total 23 164 14.0


line stmt bran cond sub pod time code
1             package Net::Wireless::802_11::Scan::FreeBSD;
2              
3 1     1   55196 use 5.006;
  1         4  
4 1     1   4 use strict;
  1         2  
  1         18  
5 1     1   3 use warnings;
  1         2  
  1         31  
6 1     1   412 use String::ShellQuote;
  1         684  
  1         51  
7 1     1   6 use base 'Error::Helper';
  1         2  
  1         406  
8              
9             =head1 NAME
10              
11             Net::Wireless::802_11::Scan::FreeBSD - A interface to the wireless interface AP scanning built into ifconfig on FreeBSD
12              
13             =head1 VERSION
14              
15             Version 0.0.0
16              
17             =cut
18              
19             our $VERSION = '0.0.0';
20              
21              
22             =head1 SYNOPSIS
23              
24             use Net::Wireless::802_11::Scan::FreeBSD;
25              
26             my $scan = Net::Wireless::802_11::Scan::FreeBSD->new();
27              
28             #scan for APs
29             my @APs=$scan->scan;
30             if ( $scan->error ){
31             warn('$scan->scan errored');
32             }
33              
34             #print some information for each AP
35             my $APs_int=0;
36             while ( defined( $APs[$APs_int] ) ){
37             print 'SSID: '.$APs[$APs_int]{'ssid'}."\n".
38             'BSSID: '.$APs[$APs_int]{'bssid'}."\n".
39             'Chan: '.$APs[$APs_int]{'chan'}."\n".
40             'Sec: ';
41              
42             my $security=none;
43             if ( $APs[$APs_int]{'WPA'} ){
44             $security='WPA1'
45             }
46             if ( $APs[$APs_int]{'RSN'} ){
47             $security='WPA2'
48             }
49              
50             print $security."\n\n";
51              
52             $APs_int++;
53             }
54              
55             =head1 METHODS
56              
57             =head2 new
58              
59             This initializes the object.
60              
61             At start the interface will be set to 'wlan0'. If you
62             want to change this, you will need to call ifSet.
63              
64             No error checking is needed as this will always succeed, as
65             long as it is being ran on FreeBSD. This will throw a permanent
66             error if $^O ne 'freebsd'.
67              
68             my $scan=Net::Wireless::802_11::Scan::FreeBSD->new();
69              
70             =cut
71              
72             sub new {
73              
74 0     0 1   my $self={
75             perror=>undef,
76             error=>undef,
77             errorString=>'',
78             errorExtra=>{
79             1=>'notFreeBSD',
80             2=>'ifUndef',
81             3=>'ifconfigError',
82             },
83             interface=>'wlan0',
84             };
85 0           bless $self;
86              
87             #this only works on FreeBSD
88 0 0         if ($^O ne 'freebsd'){
89 0           $self->{errorString}='OS not FreeBSD';
90 0           $self->{error}=1;
91 0           $self->{perror}=1;
92 0           $self->warn;
93             }
94              
95 0           return $self;
96             }
97              
98             =head2 ifGet
99              
100             This returns the current interface.
101              
102             No error checking is needed as this will always succeed.
103              
104             my $interface=$scan->ifGet;
105              
106             =cut
107              
108             sub ifGet{
109 0     0 1   my $self=$_[0];
110 0           $self->errorblank;
111 0 0         if ( $self->error ){return undef};
  0            
112              
113 0           return $self->{'interface'};
114             }
115              
116             =head2 ifSet
117              
118             This sets the interface that will be scanned.
119              
120             One argument is required and that is the interface name.
121              
122             As long as the interface is defined, there is no need to do error checking.
123              
124             #set the interface to wlan1
125             $scan->ifSet('wlan1');
126              
127             =cut
128              
129             sub ifSet{
130 0     0 1   my $self=$_[0];
131 0           my $interface=$_[1];
132 0           $self->errorblank;
133 0 0         if ( $self->error ){return undef};
  0            
134              
135 0 0         if ( ! defined( $interface ) ){
136 0           $self->{'error'}=2;
137 0           $self->{'errorString'}='No value defined for the interface';
138 0           $self->warn;
139 0           return undef;
140             }
141              
142 0           $self->{'interface'}=$interface;
143              
144 0           return undef;
145             }
146              
147             =head2 scan
148              
149             This runs "ifconfig -v $interface list scan".
150              
151             my @APs=$scan->scan;
152             use Data::Dumper;
153             print Dumper(\@APs);
154              
155             =head3 returned data
156              
157             The returned data is a array of hashes.
158              
159             =head4 ssid
160              
161             The SSID of the AP.
162              
163             This may be blank.
164              
165             =head4 bssid
166              
167             The BSSID of the AP.
168              
169             =head4 chan
170              
171             The channel it is on.
172              
173             =head4 rate
174              
175             The rate of the AP in question.
176              
177             =head4 S:N
178              
179             The signal noise ratio.
180              
181             =head4 signal
182              
183             The signal value from S:N.
184              
185             =head4 noise
186              
187             The noise value from S:N.
188              
189             =head4 int
190              
191             The beacon interval of the AP.
192              
193             =head4 caps
194              
195             This is the raw unparsed caps field.
196              
197             =head4 Authorized
198              
199             The station is permitted to send/receive data frames.
200              
201             =head4 ERP
202              
203             Extended Rate Phy (ERP). Indicates that the station is
204             operating in an 802.11g network using extended transmit
205             rates.
206              
207             =head4 HT
208              
209             The station is using HT transmit rates.
210              
211             =head4 PowerSave
212              
213             The station is operating in power save mode.
214              
215             =head4 QoS
216              
217             The station is using QoS encapsulation for data frame.
218              
219             =head4 ShortPreamble
220              
221             The station is doing short preamble to optionally improve
222             throughput performance with 802.11g and 802.11b.
223              
224             =head4 WPS
225              
226             The station in question allows the use of WPS.
227              
228             =head4 ATH
229              
230             The AP in question supports Atheros protocol extensions.
231              
232             =head4 WME
233              
234             Indicates WME support.
235              
236             =head4 WPA
237              
238             The AP supports WPA, not to be confused with WPA2.
239              
240             =head4 RSN
241              
242             The AP supports RSN, WPA2.
243              
244             =head4 VEN
245              
246             The AP supports unknown vendor-specific extensions.
247              
248             =cut
249              
250             sub scan{
251 0     0 1   my $self=$_[0];
252 0           my $interface=$_[1];
253 0           $self->errorblank;
254 0 0         if ( $self->error ){return undef};
  0            
255              
256 0           $interface=shell_quote($self->{'interface'});
257 0           my $output=`/sbin/ifconfig -v $interface scan`;
258 0           my $exitcode=$?;
259 0 0         if ( $exitcode ne '0' ){
260 0           $self->{error}=3;
261 0           $self->{errorString}='"/sbin/ifconfig -v '.$interface.' scan." exited with "'.$exitcode.'"';
262 0           $self->warn;
263 0           return undef;
264             }
265              
266 0           my @toReturn;
267              
268 0           my @outputA=split(/\n/, $output);
269 0           my $lineNumber=1;
270 0           while ( defined( $outputA[$lineNumber] ) ){
271 0           my %ap;
272 0           my $line=$outputA[$lineNumber];
273              
274 0           $ap{'ssid'}=substr($line, 0, 32);
275 0           $ap{'ssid'}=~s/[\ \t]*$//; #remove trailing white space
276 0           $line=substr($line, 34); #remove the SSID from the line
277              
278 0           my @lineA=split(/ +/, $line, 7);
279 0           $ap{'bssid'}=$lineA[0];
280 0           $ap{'chan'}=$lineA[1];
281 0           $ap{'rate'}=$lineA[2];
282 0           $ap{'S:N'}=$lineA[3];
283 0           $ap{'int'}=$lineA[4];
284 0           $ap{'caps'}=$lineA[5];
285              
286             #split the SNR so others don't have to do it later
287 0           ($ap{'signal'}, $ap{'noise'})=split(/\:/, $ap{'S:N'});
288              
289             #parse the caps as per ifconfig
290             #
291             # A Authorized. Indicates that the station is permitted to
292             # send/receive data frames.
293 0 0         if ( $ap{'caps'} =~ /A/ ){
294 0           $ap{'Authorized'}=1;
295             }else{
296 0           $ap{'Authorized'}=0;
297             }
298             # E Extended Rate Phy (ERP). Indicates that the station is
299             # operating in an 802.11g network using extended transmit
300             # rates.
301 0 0         if ( $ap{'caps'} =~ /E/ ){
302 0           $ap{'ERP'}=1;
303             }else{
304 0           $ap{'ERP'}=0;
305             }
306             # H High Throughput (HT). Indicates that the station is using
307             # HT transmit rates. If a `+' follows immediately after then
308             # the station associated using deprecated mechanisms supported
309             # only when htcompat is enabled.
310             #
311 0 0         if ( $ap{'caps'} =~ /H/ ){
312 0           $ap{'HT'}=1;
313             }else{
314 0           $ap{'HT'}=0;
315             }
316             # P Power Save. Indicates that the station is operating in
317             # power save mode.
318 0 0         if ( $ap{'caps'} =~ /P/ ){
319 0           $ap{'PowerSave'}=1;
320             }else{
321 0           $ap{'PowerSave'}=0;
322             }
323             # Q Quality of Service (QoS). Indicates that the station is
324             # using QoS encapsulation for data frame. QoS encapsulation
325             # is enabled only when WME mode is enabled.
326 0 0         if ( $ap{'caps'} =~ /Q/ ){
327 0           $ap{'QoS'}=1;
328             }else{
329 0           $ap{'QoS'}=0;
330             }
331             # S Short Preamble. Indicates that the station is doing short
332             # preamble to optionally improve throughput performance with
333             # 802.11g and 802.11b.
334 0 0         if ( $ap{'caps'} =~ /S/ ){
335 0           $ap{'ShortPreamble'}=1;
336             }else{
337 0           $ap{'ShortPreamble'}=0;
338             }
339             # T Transitional Security Network (TSN). Indicates that the
340             # station associated using TSN; see also tsn below.
341 0 0         if ( $ap{'caps'} =~ /T/ ){
342 0           $ap{'TSN'}=1;
343             }else{
344 0           $ap{'TSN'}=0;
345             }
346             # W Wi-Fi Protected Setup (WPS). Indicates that the station
347             # associated using WPS.
348 0 0         if ( $ap{'caps'} =~ /W/ ){
349 0           $ap{'WPS'}=1;
350             }else{
351 0           $ap{'WPS'}=0;
352             }
353              
354 0           $line=$lineA[6];
355 0           $line=~s/SSID\<$ap{'ssid'}\>//; #remove the SSID so we don't hit on that
356             #$line=~s/\<{1}[^\>]*\>{1}//g;
357             #print $line."\n";
358              
359             # ATH (station supports Atheros protocol extensions),
360 0 0         if ( $line =~ /\ ATH\
361 0           $ap{'ATH'}=1;
362             }else{
363 0           $ap{'ATH'}=0;
364             }
365             # WME (station supports WME),
366 0 0         if ( $line =~ /\ WME\
367 0           $ap{'WME'}=1;
368             }else{
369 0           $ap{'WME'}=0;
370             }
371             # WPA (station supports WPA),
372 0 0         if ( $line =~ /\ WPA\
373 0           $ap{'WPA'}=1;
374             }else{
375 0           $ap{'WPA'}=0;
376             }
377             # VEN (station supports unknown vendor-specific extensions)
378 0 0         if ( $line =~ /\ VEN\
379 0           $ap{'VEN'}=1;
380             }else{
381 0           $ap{'VEN'}=0;
382             }
383             # RSN https://en.wikipedia.org/wiki/IEEE_802.11i-2004
384             # appears to
385 0 0         if ( $line =~ /\ RSN\
386 0           $ap{'RSN'}=1;
387             }else{
388 0           $ap{'RSN'}=0;
389             }
390              
391              
392 0           push(@toReturn, \%ap);
393 0           $lineNumber++;
394             }
395              
396 0           return @toReturn;
397             }
398              
399             =head1 ERROR CODES/FLAGS
400              
401             For information on error handling and the like, please see the documentation on Error::Helper.
402              
403             =head2 1/notFreeBSD
404              
405             $^O ne 'freebsd'. This module only works on FreeBSD.
406              
407             =head2 2/ifUndef
408              
409             Interface not defined.
410              
411             =head2 3/ifconfigError
412              
413             Ifconfig errored when trying to run "ifconfig -v $interface list scan".
414              
415             This means it returned a non-0 exist code.
416              
417             =head1 AUTHOR
418              
419             Zane C. Bowers-Hadley, C<< >>
420              
421             =head1 BUGS
422              
423             Please report any bugs or feature requests to C, or through
424             the web interface at L. I will be notified, and then you'll
425             automatically be notified of progress on your bug as I make changes.
426              
427             =head1 SUPPORT
428              
429             You can find documentation for this module with the perldoc command.
430              
431             perldoc Net::Wireless::802_11::Scan::FreeBSD
432              
433              
434             You can also look for information at:
435              
436             =over 4
437              
438             =item * RT: CPAN's request tracker (report bugs here)
439              
440             L
441              
442             =item * AnnoCPAN: Annotated CPAN documentation
443              
444             L
445              
446             =item * CPAN Ratings
447              
448             L
449              
450             =item * Search CPAN
451              
452             L
453              
454             =back
455              
456              
457             =head1 ACKNOWLEDGEMENTS
458              
459              
460             =head1 LICENSE AND COPYRIGHT
461              
462             Copyright 2018 Zane C. Bowers-Hadley.
463              
464             This program is free software; you can redistribute it and/or modify it
465             under the terms of the the Artistic License (2.0). You may obtain a
466             copy of the full license at:
467              
468             L
469              
470             Any use, modification, and distribution of the Standard or Modified
471             Versions is governed by this Artistic License. By using, modifying or
472             distributing the Package, you accept this license. Do not use, modify,
473             or distribute the Package, if you do not accept this license.
474              
475             If your Modified Version has been derived from a Modified Version made
476             by someone other than you, you are nevertheless required to ensure that
477             your Modified Version complies with the requirements of this license.
478              
479             This license does not grant you the right to use any trademark, service
480             mark, tradename, or logo of the Copyright Holder.
481              
482             This license includes the non-exclusive, worldwide, free-of-charge
483             patent license to make, have made, use, offer to sell, sell, import and
484             otherwise transfer the Package with respect to any patent claims
485             licensable by the Copyright Holder that are necessarily infringed by the
486             Package. If you institute patent litigation (including a cross-claim or
487             counterclaim) against any party alleging that the Package constitutes
488             direct or contributory patent infringement, then this Artistic License
489             to you shall terminate on the date that such litigation is filed.
490              
491             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
492             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
493             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
494             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
495             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
496             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
497             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
498             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
499              
500              
501             =cut
502              
503             1; # End of Net::Wireless::802_11::Scan::FreeBSD