@@ -109,6 +109,12 @@ pub fn build_args<'a, 'b>() -> App<'a, 'b> {
109109 . takes_value ( true ) . value_name ( "INTERVAL_DURATION" )
110110 . help ( "Milliseconds between ARP requests" )
111111 )
112+ . arg (
113+ Arg :: with_name ( "bandwidth" ) . short ( "B" ) . long ( "bandwidth" )
114+ . takes_value ( true ) . value_name ( "BITS" )
115+ . conflicts_with ( "interval" )
116+ . help ( "Limit scan bandwidth (bits/second)" )
117+ )
112118 . arg (
113119 Arg :: with_name ( "oui-file" ) . long ( "oui-file" )
114120 . takes_value ( true ) . value_name ( "FILE_PATH" )
@@ -166,6 +172,11 @@ pub enum ProfileType {
166172 Chaos
167173}
168174
175+ pub enum ScanTiming {
176+ Interval ( u64 ) ,
177+ Bandwidth ( u64 )
178+ }
179+
169180pub struct ScanOptions {
170181 pub profile : ProfileType ,
171182 pub interface_name : Option < String > ,
@@ -177,7 +188,7 @@ pub struct ScanOptions {
177188 pub destination_mac : Option < MacAddr > ,
178189 pub vlan_id : Option < u16 > ,
179190 pub retry_count : usize ,
180- pub interval_ms : u64 ,
191+ pub scan_timing : ScanTiming ,
181192 pub randomize_targets : bool ,
182193 pub output : OutputFormat ,
183194 pub oui_file : String ,
@@ -230,6 +241,28 @@ impl ScanOptions {
230241 } ) . collect ( )
231242 } )
232243 }
244+
245+ fn compute_interval ( matches : & ArgMatches , profile : & ProfileType ) -> ScanTiming {
246+
247+ match ( matches. value_of ( "bandwidth" ) , matches. value_of ( "interval" ) ) {
248+ ( Some ( bandwidth_text) , None ) => {
249+ let bits_second: u64 = bandwidth_text. parse ( ) . unwrap_or_else ( |err| {
250+ eprintln ! ( "Expected positive number, {}" , err) ;
251+ process:: exit ( 1 ) ;
252+ } ) ;
253+ ScanTiming :: Bandwidth ( bits_second)
254+ } ,
255+ ( None , Some ( interval_text) ) => parse_to_milliseconds ( interval_text) . map ( ScanTiming :: Interval ) . unwrap_or_else ( |err| {
256+ eprintln ! ( "Expected correct interval, {}" , err) ;
257+ process:: exit ( 1 ) ;
258+ } ) ,
259+ _ => match profile {
260+ ProfileType :: Stealth => ScanTiming :: Interval ( REQUEST_MS_INTERVAL * 2 ) ,
261+ ProfileType :: Fast => ScanTiming :: Interval ( 0 ) ,
262+ _ => ScanTiming :: Interval ( REQUEST_MS_INTERVAL )
263+ }
264+ }
265+ }
233266
234267 /**
235268 * Build a new 'ScanOptions' struct that will be used in the whole CLI such
@@ -346,17 +379,7 @@ impl ScanOptions {
346379 }
347380 } ;
348381
349- let interval_ms: u64 = match matches. value_of ( "interval" ) {
350- Some ( interval_text) => parse_to_milliseconds ( interval_text) . unwrap_or_else ( |err| {
351- eprintln ! ( "Expected correct interval, {}" , err) ;
352- process:: exit ( 1 ) ;
353- } ) ,
354- None => match profile {
355- ProfileType :: Stealth => REQUEST_MS_INTERVAL * 2 ,
356- ProfileType :: Fast => 0 ,
357- _ => REQUEST_MS_INTERVAL
358- }
359- } ;
382+ let scan_timing: ScanTiming = ScanOptions :: compute_interval ( matches, & profile) ;
360383
361384 let output = match matches. value_of ( "output" ) {
362385 Some ( output_request) => {
@@ -463,7 +486,7 @@ impl ScanOptions {
463486 source_mac,
464487 vlan_id,
465488 retry_count,
466- interval_ms ,
489+ scan_timing ,
467490 randomize_targets,
468491 output,
469492 oui_file,
0 commit comments