2021-04-17 20:35:29 +00:00
use pcap ::Capture ;
use stable_eyre ::eyre ::{ eyre , Result } ;
2021-04-18 20:09:12 +00:00
use std ::collections ::HashSet ;
use std ::convert ::TryInto ;
2021-04-17 20:35:29 +00:00
mod ieee80211 {
use int_enum ::IntEnum ;
use std ::convert ::TryFrom ;
2021-04-18 20:09:12 +00:00
use std ::convert ::TryInto ;
use std ::fmt ;
2021-04-17 20:35:29 +00:00
// data/extension frames are irrelevant so just ignore their subtype
#[ derive(Clone, Copy, Debug, Eq, PartialEq) ]
pub enum FrameType {
Management ( ManagementSubtype ) ,
Control ( ControlSubtype ) ,
Data ,
Extension
}
#[ repr(u8) ]
#[ derive(Clone, Copy, Debug, Eq, PartialEq, IntEnum) ]
pub enum ManagementSubtype {
2021-04-18 20:09:12 +00:00
AssociationRequest = 0b0000 ,
AssociationResponse = 0b0001 ,
ReassociationRequest = 0b0010 ,
ReassociationResponse = 0b0011 ,
2021-04-17 20:35:29 +00:00
ProbeRequest = 0b0100 ,
ProbeResponse = 0b0101 ,
2021-04-18 20:09:12 +00:00
Beacon = 0b1000 ,
Disassociation = 0b1010 ,
Authentication = 0b1011 ,
Deauthentication = 0b1100 ,
Other = 0b1111
2021-04-17 20:35:29 +00:00
}
#[ repr(u8) ]
#[ derive(Clone, Copy, Debug, Eq, PartialEq, IntEnum) ]
pub enum ControlSubtype {
Rts = 0b1011 ,
Cts = 0b1100 ,
2021-04-18 20:09:12 +00:00
Ack = 0b1101 ,
Other = 0b1111
2021-04-17 20:35:29 +00:00
}
#[ derive(Clone, Copy, Debug, Eq, PartialEq) ]
pub struct FrameControl {
pub version : u8 ,
2021-04-18 20:09:12 +00:00
pub ftype : FrameType ,
pub to_ds : bool ,
pub from_ds : bool ,
pub more_fragments : bool ,
pub retry : bool ,
pub more_data : bool ,
pub protected : bool ,
pub htc_order : bool ,
subtype : u8
}
// read a bit out of a number (0 = LSB)
fn read_bit ( x : u8 , bit : u8 ) -> bool {
x > > bit & 0b1 = = 1
2021-04-17 20:35:29 +00:00
}
pub fn parse_frame_control ( version_type_subtype : u8 , flags : u8 ) -> Option < FrameControl > {
let subtype = version_type_subtype > > 4 & 0b1111 ;
let ftype = match version_type_subtype > > 2 & 0b11 {
2021-04-18 20:09:12 +00:00
0b00 = > FrameType ::Management ( ManagementSubtype ::try_from ( subtype ) . unwrap_or ( ManagementSubtype ::Other ) ) ,
0b01 = > FrameType ::Control ( ControlSubtype ::try_from ( subtype ) . unwrap_or ( ControlSubtype ::Other ) ) ,
2021-04-17 20:35:29 +00:00
0b10 = > FrameType ::Data ,
0b11 = > FrameType ::Extension ,
_ = > unreachable! ( )
} ;
2021-04-18 20:09:12 +00:00
//println!("{:?} {:08b}", ftype, flags);
2021-04-17 20:35:29 +00:00
Some ( FrameControl {
version : version_type_subtype & 0b11 ,
2021-04-18 20:09:12 +00:00
ftype : ftype ,
to_ds : read_bit ( flags , 0 ) ,
from_ds : read_bit ( flags , 1 ) ,
more_fragments : read_bit ( flags , 2 ) ,
retry : read_bit ( flags , 3 ) ,
more_data : read_bit ( flags , 5 ) ,
protected : read_bit ( flags , 6 ) ,
htc_order : read_bit ( flags , 7 ) ,
subtype : subtype
2021-04-17 20:35:29 +00:00
} )
}
2021-04-18 20:09:12 +00:00
#[ derive(Clone, Copy, Debug, Eq, PartialEq, Hash) ]
2021-04-17 20:50:15 +00:00
pub struct MacAddress ( [ u8 ; 6 ] ) ;
2021-04-18 20:09:12 +00:00
impl fmt ::Display for MacAddress {
fn fmt ( & self , f : & mut fmt ::Formatter < '_ > ) -> fmt ::Result {
write! ( f , " {:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x} " , self . 0 [ 0 ] , self . 0 [ 1 ] , self . 0 [ 2 ] , self . 0 [ 3 ] , self . 0 [ 4 ] , self . 0 [ 5 ] )
}
}
impl MacAddress {
pub fn is_local ( & self ) -> bool { read_bit ( self . 0 [ 0 ] , 1 ) }
pub fn is_group ( & self ) -> bool { read_bit ( self . 0 [ 0 ] , 0 ) }
}
pub fn read_addresses ( frame : & [ u8 ] ) -> Vec < MacAddress > {
let mut out = Vec ::with_capacity ( 4 ) ;
if frame . len ( ) > = 10 { out . push ( MacAddress ( frame [ 4 .. 10 ] . try_into ( ) . unwrap ( ) ) ) ; }
if frame . len ( ) > = 16 { out . push ( MacAddress ( frame [ 10 .. 16 ] . try_into ( ) . unwrap ( ) ) ) ; }
if frame . len ( ) > = 22 { out . push ( MacAddress ( frame [ 16 .. 22 ] . try_into ( ) . unwrap ( ) ) ) ; }
//if frame.len() >= 30 { out.push(MacAddress(frame[24..30].try_into().unwrap())); }
out
}
2021-04-17 20:35:29 +00:00
}
fn main ( ) -> Result < ( ) > {
let cap = Capture ::from_device ( " mon0 " ) ? . immediate_mode ( true ) ;
let mut cap = cap . open ( ) ? ;
if cap . get_datalink ( ) ! = pcap ::Linktype ::IEEE802_11_RADIOTAP { return Err ( eyre! ( " device link type wrong " ) ) }
2021-04-18 20:09:12 +00:00
let mut seen = HashSet ::new ( ) ;
2021-04-17 20:35:29 +00:00
while let Ok ( packet ) = cap . next ( ) {
//println!("{:?}", packet);
match radiotap ::parse ( packet . data ) {
Ok ( header ) = > {
let data = & packet . data [ header . length ( ) .. ] ;
match ieee80211 ::parse_frame_control ( data [ 0 ] , data [ 1 ] ) {
2021-04-18 20:09:12 +00:00
Some ( ieee80211 ::FrameControl { ftype : ieee80211 ::FrameType ::Control ( ieee80211 ::ControlSubtype ::Other ) , .. } ) = > { } ,
Some ( x ) = > {
let sequence = if data . len ( ) > = 24 {
let sn_fst = data [ 22 ] as u16 ;
let sn_snd = data [ 23 ] as u16 ;
let seq = ( sn_snd < < 4 ) + ( sn_fst > > 4 ) ;
Some ( ( seq , sn_fst & 0b1111 ) )
} else { None } ;
let addrs = ieee80211 ::read_addresses ( data ) ;
for addr in & addrs {
if ! seen . contains ( addr ) & & ! addr . is_group ( ) & & ! addr . is_local ( ) {
println! ( " attained new MAC {} from {:?} {:?} {:?} local= {} group= {} " , addr , x , addrs , sequence , addr . is_local ( ) , addr . is_group ( ) ) ;
seen . insert ( addr . clone ( ) ) ;
}
}
//println!("{:?} {:?}\nADDR={:?} SEQ={:?}\n", header.antenna_signal.unwrap().into_inner(), x, addrs, sequence);
2021-04-17 20:35:29 +00:00
} ,
_ = > { }
}
} ,
// This happens sometimes. I don't know why, since it really shouldn't (the radiotap headers are applied by the kernel). Thusly, just ignore it and hope it goes away.
Err ( e ) = > {
eprintln! ( " header decoding failed: {:?} " , e ) ;
}
}
}
Ok ( ( ) )
}