DIY-pcap 0.0.4 → 0.2.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.
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