bettercap 1.4.6 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
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