DIY-pcap 0.0.4 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/bin/pcap CHANGED
@@ -1,10 +1,67 @@
1
1
  $LOAD_PATH.unshift File.join( File.dirname(__FILE__), '..', 'lib' )
2
+ require 'rubygems'
2
3
  require 'diy-pcap'
3
4
  require 'diy/task'
4
5
 
5
- if ARGV[0].nil?
6
- puts "Usage: #{File.basename(__FILE__)} file"
7
- exit 0
8
- end
6
+ require 'optparse'
9
7
 
10
- require File.join( Dir.pwd, ARGV[0] )
8
+ options = {
9
+ :ip => "0.0.0.0:7878",
10
+ }
11
+
12
+ OptionParser.new do |opts|
13
+
14
+ opts.on("-f file", "File will be parsed") do |v|
15
+ options[:file] = v
16
+ end
17
+
18
+ opts.on("-i ip", "--ip ip", "client or server : 0.0.0.0 or 0.0.0.0:7878", "default is 0.0.0.0:7878") do |v|
19
+ options[:ip] = v
20
+ end
21
+
22
+ opts.on("-n device_name", "--name device_name", "Send or Recv device name") do |v|
23
+ options[:device_name] = v
24
+ end
25
+
26
+ opts.on_tail("--show", "Show all devices name and exit") do
27
+ require 'diy/device_finder'
28
+ DIY::DeviceFinder.pp_devices
29
+ exit 0
30
+ end
31
+
32
+ opts.on_tail('-v','--version', 'Show version') do
33
+ puts DIY::PCAP::VERSION
34
+ exit 0
35
+ end
36
+
37
+ opts.on_tail('-V', 'detail mode') do
38
+ DIY::Logger.level = ::Logger::DEBUG
39
+ end
40
+
41
+ opts.on_tail('-h','--help', 'Show this help') do
42
+ puts opts
43
+ exit 0
44
+ end
45
+ end.parse!
46
+
47
+ if options[:file]
48
+ require File.join( Dir.pwd, options[:file] )
49
+ else
50
+ ip = options[:ip]
51
+ if ip.include?(':')
52
+ uri = "druby://#{ip}"
53
+ else
54
+ uri = "druby://#{ip}:7878"
55
+ end
56
+
57
+ if options[:device_name]
58
+ device_name = options[:device_name]
59
+ else
60
+ require 'diy/device_finder'
61
+ device_name = DIY::DeviceFinder.smart_select
62
+ end
63
+ DIY::Logger.info( "Initialize Live: #{device_name}" )
64
+ device = FFI::PCap::Live.new(:dev=>device_name, :handler => FFI::PCap::Handler, :promisc => true)
65
+ worker = DIY::Worker.new(device)
66
+ DIY::WorkerKeeper.new(worker, uri).run
67
+ end
data/bin/rpcap CHANGED
@@ -1,12 +1,68 @@
1
1
  $LOAD_PATH.unshift File.join( File.dirname(__FILE__), '..', 'lib' )
2
+ require 'rubygems'
2
3
  require 'diy-pcap'
3
4
  require 'diy/task'
4
5
 
5
- $SERVER = true
6
+ require 'optparse'
6
7
 
7
- if ARGV[0].nil?
8
- puts "Usage: #{File.basename(__FILE__)} file"
9
- exit 0
10
- end
8
+ options = {
9
+ :ip => "0.0.0.0:7879",
10
+ }
11
11
 
12
- require File.join( Dir.pwd, ARGV[0] )
12
+ OptionParser.new do |opts|
13
+
14
+ opts.on("-f file", "File will be parsed") do |v|
15
+ options[:file] = v
16
+ end
17
+
18
+ opts.on("-i ip", "--ip ip", "client or server : 0.0.0.0 or 0.0.0.0:7879", "default is 0.0.0.0:7879") do |v|
19
+ options[:ip] = v
20
+ end
21
+
22
+ opts.on("-n device_name", "--name device_name", "Send or Recv device name") do |v|
23
+ options[:device_name] = v
24
+ end
25
+
26
+ opts.on_tail("--show", "Show all devices name and exit") do
27
+ require 'diy/device_finder'
28
+ DIY::DeviceFinder.pp_devices
29
+ exit 0
30
+ end
31
+
32
+ opts.on_tail('-v','--version', 'Show version') do
33
+ puts DIY::PCAP::VERSION
34
+ exit 0
35
+ end
36
+
37
+ opts.on_tail('-V', 'detail mode') do
38
+ DIY::Logger.level = ::Logger::DEBUG
39
+ end
40
+
41
+ opts.on_tail('-h','--help', 'Show this help') do
42
+ puts opts
43
+ exit 0
44
+ end
45
+ end.parse!
46
+
47
+ if options[:file]
48
+ $SERVER = true
49
+ require File.join( Dir.pwd, options[:file])
50
+ else
51
+ ip = options[:ip]
52
+ if ip.include?(':')
53
+ uri = "druby://#{ip}"
54
+ else
55
+ uri = "druby://#{ip}:7879"
56
+ end
57
+
58
+ if options[:device_name]
59
+ device_name = options[:device_name]
60
+ else
61
+ require 'diy/device_finder'
62
+ device_name = DIY::DeviceFinder.smart_select
63
+ end
64
+ DIY::Logger.info( "Initialize Live: #{device_name}" )
65
+ device = FFI::PCap::Live.new(:dev=>device_name, :handler => FFI::PCap::Handler, :promisc => true)
66
+ worker = DIY::Worker.new(device)
67
+ DIY::WorkerKeeper.new(worker, uri).run
68
+ end
data/lib/diy/builder.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require 'drb'
1
2
  module DIY
2
3
  class Builder
3
4
  def initialize(server = false, &block)
@@ -6,16 +7,6 @@ module DIY
6
7
  @server = server
7
8
  end
8
9
 
9
- def find_device
10
- @device_name ||= FFI::PCap.dump_devices[0][0]
11
- DIY::Logger.info( "Initialize Live: #{@device_name}" )
12
- @live = FFI::PCap::Live.new(:dev=>@device_name, :handler => FFI::PCap::Handler, :promisc => true)
13
- end
14
-
15
- def device(name)
16
- @device_name = name
17
- end
18
-
19
10
  def use(what)
20
11
  @strategies.unshift(what)
21
12
  end
@@ -24,6 +15,14 @@ module DIY
24
15
  @before_send_hook = block
25
16
  end
26
17
 
18
+ def find_worker_keepers
19
+ @curi ||= "druby://localhost:7878"
20
+ @suri ||= "druby://localhost:7879"
21
+ DRb.start_service
22
+ @client = DRbObject.new_with_uri(@curi)
23
+ @server = DRbObject.new_with_uri(@suri)
24
+ end
25
+
27
26
  def pcapfile(pcaps)
28
27
  DIY::Logger.info( "Initialize Offline: #{pcaps.to_a.join(', ')}" )
29
28
  @offline = DIY::Offline.new(pcaps)
@@ -31,13 +30,12 @@ module DIY
31
30
  alias pcapfiles pcapfile
32
31
 
33
32
  def run
34
- @offline ||= FFI::PCap::Offline.new('pcaps/example.pcap')
35
- @queue = Queue.new(@offline, @server)
36
- @strategy_builder = DIY::StrategyBuilder.new(@queue)
33
+ @offline ||= DIY::Offline.new('pcaps/example.pcap')
34
+ @strategy_builder = DIY::StrategyBuilder.new
37
35
  @strategies.each { |builder| @strategy_builder.add(builder) }
38
- find_device
39
- controller = Controller.new( @live, @strategy_builder )
40
- controller.before_send(&@before_send_hook)
36
+ find_worker_keepers
37
+ controller = Controller.new( @client, @server, @offline, @strategy_builder )
38
+ #~ controller.before_send(&@before_send_hook)
41
39
  controller.run
42
40
  end
43
41
 
@@ -1,46 +1,63 @@
1
1
  # encoding : utf-8
2
+
3
+ require 'timeout'
2
4
  module DIY
3
5
  class Controller
4
- def initialize(live, strategy)
5
- @live = live
6
- @recver = Recver.new(@live)
7
- @recver.add_watcher(strategy)
8
- @recver_t = nil
9
- @sender = Sender.new(@live)
10
- @queue = strategy.queue
11
- @logger = DIY::Logger
12
- end
13
- attr_accessor :logger
14
-
15
- def before_send(&block)
16
- @sender.before_send(&block)
6
+ def initialize( client, server, offline, strategy)
7
+ @client = client
8
+ @server = server
9
+ @offline = offline
10
+ @strategy = strategy
17
11
  end
18
12
 
19
13
  def run
20
- # 接收线程
21
- @recver_t = Thread.new do
22
- @recver.run
23
- end
14
+ client = @client
15
+ server = @server
24
16
 
25
- begin
26
- @queue.do_loop do |pkt|
27
- logger.info "send pkt: #{Utils.pp(pkt)}"
28
- @sender.inject(pkt)
29
- end
30
- @recver_t.join
31
- rescue HopePacketTimeoutError =>e
32
- # next offline
33
- DIY::Logger.warn("Timeout: #{e}")
34
- old = e
17
+ #clear
18
+ client.terminal
19
+ server.terminal
20
+
21
+ loop do
35
22
  begin
36
- @queue.clear_and_next_pcap
37
- retry
23
+ pkts = @offline.nexts
24
+ one_round( client, server, pkts )
25
+ client, server = server, client
26
+ rescue HopePacketTimeoutError
27
+ DIY::Logger.warn( "Timeout: Hope packet is #{pkts[0].inspect} ")
28
+ @offline.next_pcap
29
+ client,server = @client, @server
38
30
  rescue EOFError
39
- @recver.stop
40
- raise old
31
+ client.terminal
32
+ server.terminal
33
+ break
34
+ end
35
+ end
36
+ end
37
+
38
+ def one_round( client, server, pkts )
39
+ @round_count = 0 unless @round_count
40
+ @round_count += 1
41
+ DIY::Logger.info "round #{@round_count}: #{client} #{server} #{pkts[0].inspect}:(size= #{pkts.size})"
42
+ server.ready do |recv_pkt|
43
+ recv_pkt = Packet.new(recv_pkt)
44
+ @strategy.call(pkts.first, recv_pkt, pkts)
45
+ end
46
+ client.inject(pkts)
47
+ wait_recv_ok(pkts)
48
+ server.terminal
49
+ end
50
+
51
+ def wait_recv_ok(pkts)
52
+ wait_until { pkts.empty? }
53
+ end
54
+
55
+ def wait_until( timeout = 20, &block )
56
+ timeout(timeout, DIY::HopePacketTimeoutError.new("hope packet wait timeout after #{timeout} senconds") ) do
57
+ loop do
58
+ break if block.call
59
+ sleep 0.01
41
60
  end
42
- rescue EOFError
43
- @recver.stop
44
61
  end
45
62
  end
46
63
 
@@ -0,0 +1,26 @@
1
+ module DIY
2
+ class DeviceFinder
3
+ class <<self
4
+ def smart_select
5
+ ret = devices.find do |device, net|
6
+ !device.match(/dialup/) && net != nil
7
+ end
8
+ if ret
9
+ ret[0]
10
+ else
11
+ devices[0]
12
+ end
13
+ end
14
+
15
+ def pp_devices
16
+ devices.each do |device, net|
17
+ printf "%20s\t:\t%s\n", device, net
18
+ end
19
+ end
20
+
21
+ def devices
22
+ FFI::PCap.dump_devices
23
+ end
24
+ end
25
+ end
26
+ end
data/lib/diy/dig.rb CHANGED
@@ -1,11 +1,12 @@
1
1
  require 'diy/exceptions'
2
2
  require 'diy/logger'
3
3
  require 'diy/utils'
4
+ require 'diy/packet'
4
5
  require 'diy/offline'
5
- require 'diy/recver'
6
- require 'diy/sender'
7
- require 'diy/queue'
8
- require 'diy/strategy'
9
- require 'diy/strategy_builder'
6
+ require 'diy/builder'
10
7
  require 'diy/controller'
11
- require 'diy/builder'
8
+ require 'diy/strategy_builder'
9
+ require 'diy/strategy'
10
+
11
+ require 'diy/worker'
12
+ require 'diy/worker_keeper'
data/lib/diy/logger.rb CHANGED
@@ -34,6 +34,13 @@ module DIY
34
34
 
35
35
  def set(logger)
36
36
  @@logger = logger
37
+ clear_and_add(logger)
38
+ end
39
+
40
+ def level=(level)
41
+ @@logger_container.each do |logger|
42
+ logger.level = level
43
+ end
37
44
  end
38
45
 
39
46
  def add(logger)
data/lib/diy/offline.rb CHANGED
@@ -2,56 +2,126 @@
2
2
 
3
3
  module DIY
4
4
  class Offline
5
- def initialize( file_or_files)
6
- @file_or_files = file_or_files
7
- if file_or_files.kind_of?(String)
8
- @off = FFI::PCap::Offline.new(file_or_files)
9
- elsif file_or_files.kind_of?(Array)
10
- raise ZeroOfflineError," no pcap files found " if file_or_files.empty?
11
- @off = FFI::PCap::Offline.new(file_or_files[0])
12
- @position = 0
13
- end
14
- @new_pcap = true
5
+ def initialize( pcap_files )
6
+ @pcap_files = [ pcap_files ] if pcap_files.kind_of?(String)
7
+ @pcap_files ||= pcap_files
8
+ @off = FFI::PCap::Offline.new(@pcap_files[0])
9
+ # 记录文件在目录中的位置
10
+ @position = 0
11
+ # 记录包在当前文件的位置
15
12
  @num = 0
13
+
14
+ @tmp_pcap = nil
16
15
  end
17
16
 
18
- def next
19
- pkt = @off.next
17
+ def nexts
18
+ ret = []
19
+ # 取一个
20
+ pkt = fetch_one
20
21
  if pkt.nil?
21
- begin
22
- next_pcap
23
- pkt = @off.next
24
- rescue EOFError
25
- pkt = nil
22
+ next_pcap
23
+ pkt = fetch_one
24
+ end
25
+
26
+ ret << pkt
27
+ op = "=="
28
+ if ! fetch_cached_mac
29
+ cached_mac(pkt)
30
+ else
31
+ if Utils.src_mac(pkt) != fetch_cached_mac
32
+ op = "!="
26
33
  end
27
34
  end
28
35
 
29
- #record num of pkt
30
- @num += 1 if pkt
36
+ loop do
37
+ pkt = self.next
38
+ if pkt.nil?
39
+ return ret
40
+ end
41
+
42
+ if compare_mac( op, Utils.src_mac(pkt), fetch_cached_mac)
43
+ ret << pkt
44
+ else
45
+ cached(pkt)
46
+ return ret
47
+ end
48
+
49
+ end
31
50
 
51
+ end
52
+
53
+ def compare_mac( op, mac1, mac2)
54
+ if op == "=="
55
+ mac1 == mac2
56
+ elsif op == "!="
57
+ mac1 != mac2
58
+ else
59
+ raise "error op"
60
+ end
61
+ end
62
+
63
+ def fetch_one
64
+ pkt = fetch_cache
65
+ if pkt.nil?
66
+ pkt = self.next
67
+ end
32
68
  pkt
33
69
  end
70
+ protected
71
+ # 只处理当前文件
72
+ def next
73
+ pkt = @off.next
74
+ @num += 1
75
+ return nil if pkt.nil?
76
+
77
+ return Packet.new(pkt.copy.body, fullname)
78
+ end
79
+
80
+ def cached(pkt)
81
+ raise "Can't cached one pkt twice" if @tmp_pcap
82
+ @tmp_pcap = pkt
83
+ end
84
+
85
+ def cached_mac(pkt)
86
+ @src = Utils.src_mac(pkt)
87
+ end
88
+
89
+ def fetch_cached_mac
90
+ @src
91
+ end
92
+
93
+ def clear_cached_mac
94
+ @src = nil
95
+ end
96
+
97
+ def fetch_cache
98
+ if @tmp_pcap
99
+ tmp = @tmp_pcap
100
+ @tmp_pcap = nil
101
+ return tmp
102
+ end
103
+ return nil
104
+ end
34
105
 
35
106
  def first_pkt?
107
+ puts @num
36
108
  @num == 1
37
109
  end
38
-
110
+ public
39
111
  def next_pcap
40
- if @file_or_files.kind_of?(String) or @position >= @file_or_files.size - 1
112
+ if @position >= @pcap_files.size - 1
41
113
  raise EOFError, " end of pcaps "
42
114
  end
43
115
  @position += 1
44
- DIY::Logger.info("pcap file changed: #{@file_or_files[@position]}")
45
- @off = FFI::PCap::Offline.new(@file_or_files[@position])
116
+ DIY::Logger.info("pcap file changed: #{@pcap_files[@position]}")
117
+ @off = FFI::PCap::Offline.new(@pcap_files[@position])
46
118
  @num = 0
119
+ clear_cached_mac
120
+ fetch_cache
47
121
  end
48
122
 
49
123
  def filename
50
- if @file_or_files.kind_of?(String)
51
- @file_or_files
52
- else
53
- @file_or_files[@position]
54
- end
124
+ @pcap_files[@position]
55
125
  end
56
126
 
57
127
  def fullname