bettercap 1.4.6 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/bin/bettercap +1 -1
  3. data/lib/bettercap.rb +1 -0
  4. data/lib/bettercap/context.rb +63 -70
  5. data/lib/bettercap/discovery/agents/base.rb +2 -2
  6. data/lib/bettercap/discovery/thread.rb +5 -4
  7. data/lib/bettercap/firewalls/base.rb +2 -4
  8. data/lib/bettercap/firewalls/{osx.rb → bsd.rb} +3 -3
  9. data/lib/bettercap/firewalls/linux.rb +2 -2
  10. data/lib/bettercap/firewalls/redirection.rb +5 -2
  11. data/lib/bettercap/logger.rb +6 -11
  12. data/lib/bettercap/memory.rb +56 -0
  13. data/lib/bettercap/monkey/em-proxy/proxy.rb +23 -0
  14. data/lib/bettercap/monkey/packetfu/pcap.rb +51 -0
  15. data/lib/bettercap/network/arp_reader.rb +2 -2
  16. data/lib/bettercap/network/network.rb +2 -2
  17. data/lib/bettercap/network/packet_queue.rb +2 -2
  18. data/lib/bettercap/network/protos/base.rb +8 -5
  19. data/lib/bettercap/network/protos/dhcp.rb +5 -124
  20. data/lib/bettercap/network/target.rb +7 -2
  21. data/lib/bettercap/options/core_options.rb +189 -0
  22. data/lib/bettercap/options/options.rb +167 -0
  23. data/lib/bettercap/options/proxy_options.rb +258 -0
  24. data/lib/bettercap/options/server_options.rb +71 -0
  25. data/lib/bettercap/options/sniff_options.rb +90 -0
  26. data/lib/bettercap/options/spoof_options.rb +71 -0
  27. data/lib/bettercap/proxy/{module.rb → http/module.rb} +8 -4
  28. data/lib/bettercap/proxy/{modules → http/modules}/injectcss.rb +2 -2
  29. data/lib/bettercap/proxy/{modules → http/modules}/injecthtml.rb +2 -2
  30. data/lib/bettercap/proxy/{modules → http/modules}/injectjs.rb +2 -2
  31. data/lib/bettercap/proxy/{proxy.rb → http/proxy.rb} +5 -2
  32. data/lib/bettercap/proxy/{request.rb → http/request.rb} +4 -0
  33. data/lib/bettercap/proxy/{response.rb → http/response.rb} +3 -0
  34. data/lib/bettercap/proxy/{ssl → http/ssl}/authority.rb +3 -1
  35. data/lib/bettercap/proxy/{ssl → http/ssl}/bettercap-ca.pem +0 -0
  36. data/lib/bettercap/proxy/{ssl → http/ssl}/server.rb +3 -1
  37. data/lib/bettercap/proxy/{sslstrip → http/sslstrip}/cookiemonitor.rb +2 -0
  38. data/lib/bettercap/proxy/{sslstrip → http/sslstrip}/lock.ico +0 -0
  39. data/lib/bettercap/proxy/{sslstrip → http/sslstrip}/strip.rb +4 -2
  40. data/lib/bettercap/proxy/{streamer.rb → http/streamer.rb} +7 -4
  41. data/lib/bettercap/proxy/stream_logger.rb +25 -9
  42. data/lib/bettercap/proxy/tcp/module.rb +75 -0
  43. data/lib/bettercap/proxy/tcp/proxy.rb +123 -0
  44. data/lib/bettercap/proxy/thread_pool.rb +1 -1
  45. data/lib/bettercap/sniffer/parsers/post.rb +1 -1
  46. data/lib/bettercap/sniffer/parsers/url.rb +1 -1
  47. data/lib/bettercap/sniffer/sniffer.rb +23 -17
  48. data/lib/bettercap/spoofers/arp.rb +21 -9
  49. data/lib/bettercap/spoofers/base.rb +12 -16
  50. data/lib/bettercap/spoofers/icmp.rb +4 -5
  51. data/lib/bettercap/spoofers/none.rb +0 -1
  52. data/lib/bettercap/version.rb +1 -1
  53. metadata +48 -19
  54. data/lib/bettercap/firewalls/openbsd.rb +0 -77
  55. data/lib/bettercap/options.rb +0 -600
@@ -0,0 +1,23 @@
1
+ class Proxy
2
+
3
+ def self.start(options, &blk)
4
+ # epoll is not supported on OSX!
5
+ # EM.epoll
6
+ EM.run do
7
+ # We'll take care of this.
8
+ #
9
+ # trap("TERM") { stop }
10
+ # trap("INT") { stop }
11
+
12
+ EventMachine::start_server(options[:host], options[:port],
13
+ EventMachine::ProxyServer::Connection, options) do |c|
14
+ c.instance_eval(&blk)
15
+ end
16
+ end
17
+ end
18
+
19
+ def self.stop
20
+ EventMachine.stop
21
+ rescue
22
+ end
23
+ end
@@ -0,0 +1,51 @@
1
+ # encoding: UTF-8
2
+ =begin
3
+
4
+ BETTERCAP
5
+
6
+ Author : Simone 'evilsocket' Margaritelli
7
+ Email : evilsocket@gmail.com
8
+ Blog : http://www.evilsocket.net/
9
+
10
+ This project is released under the GPL 3 license.
11
+
12
+ =end
13
+ module PacketFu
14
+
15
+ class PcapHeader
16
+ # Reads a string to populate the object.
17
+ # Conversion from big to little shouldn't be that big of a deal.
18
+ def read(str)
19
+ force_binary(str)
20
+ return self if str.nil?
21
+ str.force_encoding(Encoding::BINARY) if str.respond_to? :force_encoding
22
+
23
+ # Handle little endian pcap
24
+ if str[0,4] == self[:magic].to_s
25
+ self[:magic].read str[0,4]
26
+ self[:ver_major].read str[4,2]
27
+ self[:ver_minor].read str[6,2]
28
+ self[:thiszone].read str[8,4]
29
+ self[:sigfigs].read str[12,4]
30
+ self[:snaplen].read str[16,4]
31
+ self[:network].read str[20,4]
32
+ # Handle big endian pcap
33
+ elsif str[0,4] == MAGIC_BIG.to_s
34
+ # Since PcapFile.read uses our endianess, set it to 'big' anyway.
35
+ self[:endian] = :big
36
+
37
+ self[:magic].read str[0,4].reverse
38
+ self[:ver_major].read str[4,2].reverse
39
+ self[:ver_minor].read str[6,2].reverse
40
+ self[:thiszone].read str[8,4].reverse
41
+ self[:sigfigs].read str[12,4].reverse
42
+ self[:snaplen].read str[16,4].reverse
43
+ self[:network].read str[20,4].reverse
44
+ else
45
+ raise "Incorrect magic for libpcap"
46
+ end
47
+ self
48
+ end
49
+ end
50
+
51
+ end
@@ -21,8 +21,8 @@ class ArpReader
21
21
  def self.parse( ctx )
22
22
  targets = []
23
23
  self.parse_cache do |ip,mac|
24
- if ip != ctx.gateway and ip != ctx.ifconfig[:ip_saddr]
25
- if ctx.options.ignore_ip?(ip)
24
+ if ip != ctx.gateway.ip and ip != ctx.ifconfig[:ip_saddr]
25
+ if ctx.options.core.ignore_ip?(ip)
26
26
  Logger.debug "Ignoring #{ip} ..."
27
27
  else
28
28
  # reuse Target object if it's already a known address
@@ -18,7 +18,7 @@ class << self
18
18
  # Return the current network gateway or nil.
19
19
  def get_gateway
20
20
  nstat = Shell.execute('netstat -nr')
21
- iface = Context.get.options.iface
21
+ iface = Context.get.options.core.iface
22
22
 
23
23
  Logger.debug "NETSTAT:\n#{nstat}"
24
24
 
@@ -54,7 +54,7 @@ class << self
54
54
  # Return a list of BetterCap::Target objects found on the network, given a
55
55
  # BetterCap::Context ( +ctx+ ) and a +timeout+ in seconds for the operation.
56
56
  def get_alive_targets( ctx )
57
- if ctx.options.should_discover_hosts?
57
+ if ctx.options.core.should_discover_hosts?
58
58
  start_agents( ctx )
59
59
  else
60
60
  Logger.debug 'Using current ARP cache.'
@@ -29,13 +29,13 @@ class PacketQueue
29
29
  @udp = UDPSocket.new
30
30
  @queue = Queue.new
31
31
  @workers = (0...nworkers).map { ::Thread.new { worker } }
32
+ @ctx = Context.get
32
33
  end
33
34
 
34
35
  # Push a packet to the queue.
35
36
  def push(packet)
36
- Context.run_gc if @queue.size == 0
37
-
38
37
  @queue.push(packet)
38
+ @ctx.memory.optimize! if ( @queue.size == 1 )
39
39
  end
40
40
 
41
41
  # Wait for the packet queue to be empty.
@@ -98,11 +98,6 @@ class Base
98
98
  offset = offset( info, pkt, offset )
99
99
 
100
100
  value = data[offset..offset + size - 1].bytes.pack('c*')
101
- if info[:opts].has_key?(:check)
102
- if value != info[:opts][:check].force_encoding('ASCII-8BIT')
103
- raise "Unexpected value '#{value}', expected '#{info[:opts][:check]}' ."
104
- end
105
- end
106
101
  offset += size
107
102
 
108
103
  when :stringz
@@ -116,6 +111,14 @@ class Base
116
111
 
117
112
  end
118
113
 
114
+ if info[:opts].has_key?(:check)
115
+ check = info[:opts][:check]
116
+ check = check.force_encoding('ASCII-8BIT') if check.respond_to? :force_encoding
117
+ if value != check
118
+ raise "Unexpected value '#{value}', expected '#{check}' ."
119
+ end
120
+ end
121
+
119
122
  pkt.send("#{name}=", value)
120
123
  end
121
124
 
@@ -28,125 +28,6 @@ OP_MESSAGETYPES = {
28
28
  }
29
29
 
30
30
  OP_CONSTANTS = {
31
- # DHCP Options
32
- :DHCPPad => 0,
33
- :DHCPSubnetMask => 1,
34
- :DHCPTimeOffset => 2,
35
- :DHCPRouter => 3,
36
- :DHCPTimeServer => 4,
37
- :DHCPNameServer => 5,
38
- :DHCPDNS => 6,
39
- :DHCPLogServer => 7,
40
- :DHCPQuoteServer => 8,
41
- :DHCPLPRServer => 9,
42
- :DHCPImpressServer => 10,
43
- :DHCPRLServer => 11,
44
- :DHCPHostName => 12,
45
- :DHCPBootFileSize => 13,
46
- :DHCPMeritDumpFile => 14,
47
- :DHCPDomainName => 15,
48
- :DHCPSwapServer => 16,
49
- :DHCPRootPath => 17,
50
- :DHCPExtensionsPath => 18,
51
- :DHCPIPForwarding => 19,
52
- :DHCPNonLocalRouting => 20,
53
- :DHCPPolicyFilter => 21,
54
- :DHCPMaximumDRSize => 22, # Datagram reassembly size
55
- :DHCPDefaultIPTTL => 23,
56
- :DHCPPathMTUAgingTimeout => 24,
57
- :DHCPPathMTUPlateauTable => 25,
58
- :DHCPInterfaceMTU => 26,
59
- :DHCPAllSubnetsLocal => 27,
60
- :DHCPBroadcastAddress => 28,
61
- :DHCPPerformMask => 29, # Perform mask discovery
62
- :DHCPMaskSupplier => 30, # Zelda flashbacks
63
- :DHCPPerformRouter => 31, # Perform router discovery
64
- :DHCPRouterSolicitation => 32, # Router Solicitation Address
65
- :DHCPStaticRoutingEnable => 33,
66
- :DHCPTrailerEncap => 34, # Trailer Encapsulation
67
- :DHCPArpCacheTimeout => 35,
68
- :DHCPEthernetEncap => 36, # ethernet encapsulation
69
- :DHCPDefaultTCPTTL => 37,
70
- :DHCPTCPKeepAliveInt => 38, # TCP Keepalive interval
71
- :DHCPTCPKeepAliveGB => 39, # TCP Keepalive garbage
72
- :DHCPNISDomain => 40,
73
- :DHCPNISServer => 41,
74
- :DHCPNTPServers => 42,
75
- :DHCPVendorSpecificInfo => 43,
76
- :DHCPNetBIOSNameServer => 44,
77
- :DHCPNetBIOSDDS => 45,
78
- :DHCPNetBIOSNodeType => 46,
79
- :DHCPNetBIOSScope => 47,
80
- :DHCPXWindowSystemFont => 48, # XWindow Font server
81
- :DHCPXWindowSystemDM => 49, # Xwindow System Display Server
82
- :DHCPRequestedIPAddress => 50,
83
- :DHCPIPAddressLeaseTime => 51,
84
- :DHCPOptionOverload => 52,
85
- :DHCPMessageType => 53,
86
- :DHCPServerIdentifier => 54,
87
- :DHCPParameters => 55,
88
- :DHCPMessage => 56,
89
- :DHCPMaxDHCPMessageSize => 57,
90
- :DHCPRenewTimeValue => 58,
91
- :DHCPRebindingTimeValue => 59,
92
- :DHCPClassIdentifier => 60,
93
- :DHCPClientIdentifier => 61,
94
- :DHCPNetWareIPDomainName => 62,
95
- :DHCPNetWareIPInformation => 63,
96
- :DHCPNISClientDomain => 64,
97
- :DHCPNISServers => 65,
98
- :DHCPTFTPServerName => 66,
99
- :DHCPBootFileName => 67,
100
- :DHCPMobileIPHomeAgent => 68,
101
- :DHCPSMTPServer => 69,
102
- :DHCPPOPServer => 70,
103
- :DHCPNNTPServer => 71,
104
- :DHCPDefaultWWWServer => 72,
105
- :DHCPDefaultFingerServer => 73,
106
- :DHCPDefaultIRCServer => 74,
107
- :DHCPStreetTalkServer => 75,
108
- :DHCPStreetTalkDAS => 76,
109
- :DHCPUserClassInformation => 77,
110
- :DHCPSLPDirectoryAgent => 78,
111
- :DHCPSLPServiceScope => 79,
112
- :DHCPRapidCommit => 80,
113
- :DHCPFQDN => 81,
114
- :DHCPRelayAgentInformation => 82,
115
- :DHCPInternetStorageNameService => 83,
116
- # ??
117
- :DHCPNDSServers => 85,
118
- :DHCPNDSTreeName => 86,
119
- :DHCPNDSContext => 87,
120
- :DHCPBCMCSContDomainNameList => 88,
121
- :DHCPBCMCSContIPV4AddressList => 89,
122
- :DHCPAuthentication => 90,
123
- :DHCPClientLastTransactTime => 91,
124
- :DHCPAssociatedIP => 92,
125
- :DHCPClientSystemArchType => 93,
126
- :DHCPClientNetworkInterfaceIdent => 94,
127
- :DHCPLDAP => 95,
128
- # ??
129
- :DHCPClientMachineIdent => 97,
130
- :DHCPOGUA => 98,
131
- # ??
132
- :DHCPAutonomousSystemNumber => 109,
133
- # ??
134
- :DHCPNetInfoParentServerAddress => 112,
135
- :DHCPNetInfoParentServerTag => 113,
136
- :DHCPURL => 114,
137
- :DHCPAutoConfigure => 116,
138
- :DHCPNameServiceSearch => 117,
139
- :DHCPSubnetSelection => 118,
140
- :DHCPDNSDomainSearchList => 119,
141
- :DHCPSIPServers => 120,
142
- :DHCPClasslessStaticRoute => 121,
143
- :DHCPCableLabsClientConfig => 122,
144
- :DHCPGeoConf => 123,
145
- # ??
146
- :DHCPProxyAutoDiscovery => 252
147
- }
148
-
149
- OP_CONSTANTS_REV = {
150
31
  0 => :Pad,
151
32
  1 => :SubnetMask,
152
33
  2 => :TimeOffset,
@@ -287,21 +168,21 @@ class Packet < Network::Protos::Base
287
168
  bytes :dhcpoptions
288
169
 
289
170
  def type
290
- self.each_option( :MessageType ) do |opt,data|
171
+ self.each_option( :MessageType ) do |_,data|
291
172
  return OP_MESSAGETYPES[ data[0] ]
292
173
  end
293
174
  OP_MESSAGETYPES[ @op ]
294
175
  end
295
176
 
296
177
  def client_identifier
297
- self.each_option( :ClientIdentifier ) do |opt,data|
178
+ self.each_option( :ClientIdentifier ) do |_,data|
298
179
  return data.pack('c*')
299
180
  end
300
181
  end
301
182
 
302
183
  def authentication
303
184
  # Thank you Wireshark BOOTP dissector!
304
- self.each_option( :Authentication ) do |opt,data|
185
+ self.each_option( :Authentication ) do |_,data|
305
186
  auth = {}
306
187
 
307
188
  auth['Protocol'] = AUTH_PROTOCOLS[ data[0] ]
@@ -333,8 +214,8 @@ class Packet < Network::Protos::Base
333
214
  data = self.dhcpoptions[offset..offset+len-1]
334
215
  offset += len
335
216
 
336
- if sym.nil? or OP_CONSTANTS_REV[opt] == sym
337
- yield( OP_CONSTANTS_REV[opt], data )
217
+ if sym.nil? or OP_CONSTANTS[opt] == sym
218
+ yield( OP_CONSTANTS[opt], data )
338
219
  end
339
220
  end
340
221
  end
@@ -58,7 +58,7 @@ class Target
58
58
  @mac = Target.normalized_mac(mac) unless mac.nil?
59
59
  @vendor = Target.lookup_vendor(@mac) unless mac.nil?
60
60
  @hostname = nil
61
- @resolver = Thread.new { resolve! } unless Context.get.options.no_target_nbns or @ip.nil?
61
+ @resolver = Thread.new { resolve! } unless Context.get.options.core.no_target_nbns or @ip.nil?
62
62
  end
63
63
 
64
64
  # Return the integer representation of the +ip+ attribute which can be
@@ -67,11 +67,16 @@ class Target
67
67
  @ip.split('.').inject(0) {|total,value| (total << 8 ) + value.to_i}
68
68
  end
69
69
 
70
+ # Return true if both the ip and mac are not nil.
71
+ def spoofable?
72
+ ( !@ip.nil? and !@mac.nil? )
73
+ end
74
+
70
75
  # +mac+ attribute setter, it will normalize the +value+ and perform
71
76
  # a vendor lookup.
72
77
  def mac=(value)
73
78
  @mac = Target.normalized_mac(value)
74
- @vendor = Target.lookup_vendor(@mac) if not @mac.nil?
79
+ @vendor = Target.lookup_vendor(@mac) unless @mac.nil?
75
80
  end
76
81
 
77
82
  # Return a verbose string representation of this object.
@@ -0,0 +1,189 @@
1
+ # encoding: UTF-8
2
+ =begin
3
+
4
+ BETTERCAP
5
+
6
+ Author : Simone 'evilsocket' Margaritelli
7
+ Email : evilsocket@gmail.com
8
+ Blog : http://www.evilsocket.net/
9
+
10
+ This project is released under the GPL 3 license.
11
+
12
+ =end
13
+
14
+ module BetterCap
15
+
16
+ class CoreOptions
17
+ # Network interface.
18
+ attr_accessor :iface
19
+ # Gateway IP address.
20
+ attr_accessor :gateway
21
+ # Comma separated list of targets.
22
+ attr_accessor :targets
23
+ # Comma separated list of ip addresses to ignore.
24
+ attr_accessor :ignore
25
+ # If true will disable active network discovery, the program will just use
26
+ # the current ARP cache.
27
+ attr_accessor :arpcache
28
+ # If true, targets NBNS hostname resolution won't be performed.
29
+ attr_accessor :no_target_nbns
30
+ # Log file name.
31
+ attr_accessor :logfile
32
+ # If true the Logger will prepend timestamps to each line.
33
+ attr_accessor :log_timestamp
34
+ # If true will suppress every log message which is not an error or a warning.
35
+ attr_accessor :silent
36
+ # If true will enable debug messages.
37
+ attr_accessor :debug
38
+ # If different than 0, this time will be used as a delay while sending packets.
39
+ attr_accessor :packet_throttle
40
+ # If true, bettercap will check for updates then exit.
41
+ attr_accessor :check_updates
42
+
43
+ def initialize( iface )
44
+ @iface = iface
45
+ @gateway = nil
46
+ @targets = nil
47
+ @logfile = nil
48
+ @log_timestamp = false
49
+ @silent = false
50
+ @debug = false
51
+ @ignore = nil
52
+ @arpcache = false
53
+ @no_target_nbns = false
54
+ @packet_throttle = 0.0
55
+ @check_updates = false
56
+ end
57
+
58
+ def parse!( ctx, opts )
59
+ opts.separator ""
60
+ opts.separator "MAIN:".bold
61
+ opts.separator ""
62
+
63
+ opts.on( '-I', '--interface IFACE', 'Network interface name - default: ' + @iface.to_s.yellow ) do |v|
64
+ @iface = v
65
+ end
66
+
67
+ opts.on( '-G', '--gateway ADDRESS', 'Manually specify the gateway address, if not specified the current gateway will be retrieved and used. ' ) do |v|
68
+ @gateway = v
69
+ raise BetterCap::Error, "The specified gateway '#{v}' is not a valid IPv4 address." unless Network::Validator.is_ip?(v)
70
+ end
71
+
72
+ opts.on( '-T', '--target ADDRESS1,ADDRESS2', 'Target IP addresses, if not specified the whole subnet will be targeted.' ) do |v|
73
+ self.targets = v
74
+ end
75
+
76
+ opts.on( '--ignore ADDRESS1,ADDRESS2', 'Ignore these addresses if found while searching for targets.' ) do |v|
77
+ self.ignore = v
78
+ end
79
+
80
+ opts.on( '--no-discovery', "Do not actively search for hosts, just use the current ARP cache, default to #{'false'.yellow}." ) do
81
+ @arpcache = true
82
+ end
83
+
84
+ opts.on( '--no-target-nbns', 'Disable target NBNS hostname resolution.' ) do
85
+ @no_target_nbns = true
86
+ end
87
+
88
+ opts.on( '--packet-throttle NUMBER', 'Number of seconds ( can be a decimal number ) to wait between each packet to be sent.' ) do |v|
89
+ @packet_throttle = v.to_f
90
+ raise BetterCap::Error, "Invalid packet throttle value specified." if @packet_throttle <= 0.0
91
+ end
92
+
93
+ opts.on( '--check-updates', 'Will check if any update is available and then exit.' ) do
94
+ @check_updates = true
95
+ end
96
+
97
+ opts.on( '-h', '--help', 'Display the available options.') do
98
+ puts opts
99
+ puts "\nFor examples & docs please visit " + "http://bettercap.org/docs/".bold
100
+ exit
101
+ end
102
+
103
+ opts.separator ""
104
+ opts.separator "LOGGING:".bold
105
+ opts.separator ""
106
+
107
+ opts.on( '-O', '--log LOG_FILE', 'Log all messages into a file, if not specified the log messages will be only print into the shell.' ) do |v|
108
+ @logfile = v
109
+ end
110
+
111
+ opts.on( '--log-timestamp', 'Enable logging with timestamps for each line, disabled by default.' ) do
112
+ @log_timestamp = true
113
+ end
114
+
115
+ opts.on( '-D', '--debug', 'Enable debug logging.' ) do
116
+ @debug = true
117
+ end
118
+
119
+ opts.on( '--silent', "Suppress every message which is not an error or a warning, default to #{'false'.yellow}." ) do
120
+ @silent = true
121
+ end
122
+
123
+ end
124
+
125
+ def validate!
126
+ raise BetterCap::Error, 'This software must run as root.' unless Process.uid == 0
127
+ raise BetterCap::Error, 'No default interface found, please specify one with the -I argument.' if @iface.nil?
128
+ end
129
+
130
+ def discovery?
131
+ ( @targets.nil? and !@arpcache )
132
+ end
133
+
134
+ # Split specified targets and parse them ( either as IP or MAC ), will raise a
135
+ # BetterCap::Error if one or more invalid addresses are specified.
136
+ def targets=(value)
137
+ @targets = []
138
+
139
+ value.split(",").each do |t|
140
+ if Network::Validator.is_ip?(t) or Network::Validator.is_mac?(t)
141
+ @targets << Network::Target.new(t)
142
+
143
+ elsif Network::Validator.is_range?(t)
144
+ Network::Validator.each_in_range( t ) do |address|
145
+ @targets << Network::Target.new(address)
146
+ end
147
+
148
+ elsif Network::Validator.is_netmask?(t)
149
+ Network::Validator.each_in_netmask(t) do |address|
150
+ @targets << Network::Target.new(address)
151
+ end
152
+
153
+ else
154
+ raise BetterCap::Error, "Invalid target specified '#{t}', valid formats are IP addresses, "\
155
+ "MAC addresses, IP ranges ( 192.168.1.1-30 ) or netmasks ( 192.168.1.1/24 ) ."
156
+ end
157
+ end
158
+ end
159
+
160
+ # Setter for the #ignore attribute, will raise a BetterCap::Error if one
161
+ # or more invalid IP addresses are specified.
162
+ def ignore=(value)
163
+ @ignore = value.split(",")
164
+ valid = @ignore.select { |target| Network::Validator.is_ip?(target) }
165
+
166
+ raise BetterCap::Error, "Invalid ignore addresses specified." if valid.empty?
167
+
168
+ invalid = @ignore - valid
169
+ invalid.each do |target|
170
+ Logger.warn "Not a valid address: #{target}"
171
+ end
172
+
173
+ @ignore = valid
174
+
175
+ Logger.warn "Ignoring #{valid.join(", ")} ."
176
+ end
177
+
178
+ # Return true if the +ip+ address needs to be ignored, otherwise false.
179
+ def ignore_ip?(ip)
180
+ !@ignore.nil? and @ignore.include?(ip)
181
+ end
182
+
183
+ # Return true if active host discovery is enabled, otherwise false.
184
+ def should_discover_hosts?
185
+ !@arpcache
186
+ end
187
+ end
188
+
189
+ end