DIY-pcap 0.4.1 → 0.4.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -4
- data/DIY-pcap.gemspec +17 -17
- data/Gemfile +3 -3
- data/Rakefile +1 -1
- data/lib/DIY-pcap.rb +2 -2
- data/lib/diy/command.rb +7 -1
- data/lib/diy/controller.rb +10 -15
- data/lib/diy/live.rb +9 -2
- data/lib/diy/parser/mu/pcap/ethernet.rb +148 -148
- data/lib/diy/parser/mu/pcap/header.rb +75 -75
- data/lib/diy/parser/mu/pcap/io_pair.rb +67 -67
- data/lib/diy/parser/mu/pcap/io_wrapper.rb +76 -76
- data/lib/diy/parser/mu/pcap/ip.rb +61 -61
- data/lib/diy/parser/mu/pcap/ipv4.rb +257 -257
- data/lib/diy/parser/mu/pcap/ipv6.rb +148 -148
- data/lib/diy/parser/mu/pcap/packet.rb +104 -104
- data/lib/diy/parser/mu/pcap/pkthdr.rb +155 -155
- data/lib/diy/parser/mu/pcap/reader.rb +61 -61
- data/lib/diy/parser/mu/pcap/reader/http_family.rb +170 -170
- data/lib/diy/parser/mu/pcap/sctp.rb +367 -367
- data/lib/diy/parser/mu/pcap/sctp/chunk.rb +123 -123
- data/lib/diy/parser/mu/pcap/sctp/chunk/data.rb +134 -134
- data/lib/diy/parser/mu/pcap/sctp/chunk/init.rb +100 -100
- data/lib/diy/parser/mu/pcap/sctp/chunk/init_ack.rb +68 -68
- data/lib/diy/parser/mu/pcap/sctp/parameter.rb +110 -110
- data/lib/diy/parser/mu/pcap/sctp/parameter/ip_address.rb +48 -48
- data/lib/diy/parser/mu/pcap/stream_packetizer.rb +72 -72
- data/lib/diy/parser/mu/pcap/tcp.rb +505 -505
- data/lib/diy/parser/mu/pcap/udp.rb +69 -69
- data/lib/diy/parser/mu/scenario/pcap.rb +172 -172
- data/lib/diy/parser/mu/scenario/pcap/fields.rb +50 -50
- data/lib/diy/parser/mu/scenario/pcap/rtp.rb +71 -71
- data/lib/diy/parser/pcap.rb +109 -109
- data/lib/diy/version.rb +1 -1
- metadata +7 -9
@@ -1,50 +1,50 @@
|
|
1
|
-
# http://www.mudynamics.com
|
2
|
-
# http://labs.mudynamics.com
|
3
|
-
# http://www.pcapr.net
|
4
|
-
|
5
|
-
require 'mu/scenario/pcap'
|
6
|
-
|
7
|
-
module Mu
|
8
|
-
class Scenario
|
9
|
-
module Pcap
|
10
|
-
|
11
|
-
class Fields
|
12
|
-
FIELDS = [
|
13
|
-
:rtp,
|
14
|
-
:"rtp.setup-frame"
|
15
|
-
].freeze
|
16
|
-
FIELD_COUNT = FIELDS.length
|
17
|
-
SEPARATOR = "\xff".freeze
|
18
|
-
TSHARK_OPTS = "-Eseparator='#{SEPARATOR}'"
|
19
|
-
FIELDS.each do |field|
|
20
|
-
TSHARK_OPTS << " -e #{field}"
|
21
|
-
end
|
22
|
-
TSHARK_OPTS.freeze
|
23
|
-
|
24
|
-
def self.readline io
|
25
|
-
if ::IO.select [ io ], nil, nil, Pcap::TSHARK_READ_TIMEOUT
|
26
|
-
return io.readline.chomp
|
27
|
-
end
|
28
|
-
|
29
|
-
raise Errno::ETIMEDOUT, "read timed out"
|
30
|
-
end
|
31
|
-
|
32
|
-
def self.next_from_io io
|
33
|
-
if line = readline(io)
|
34
|
-
fields = line.split SEPARATOR, FIELD_COUNT
|
35
|
-
hash = {}
|
36
|
-
FIELDS.each do |key|
|
37
|
-
val = fields.shift
|
38
|
-
hash[key] = val.empty? ? nil : val
|
39
|
-
end
|
40
|
-
return hash
|
41
|
-
end
|
42
|
-
rescue Exception => e
|
43
|
-
Pcap.warning e.message
|
44
|
-
return nil
|
45
|
-
end
|
46
|
-
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
1
|
+
# http://www.mudynamics.com
|
2
|
+
# http://labs.mudynamics.com
|
3
|
+
# http://www.pcapr.net
|
4
|
+
|
5
|
+
require 'mu/scenario/pcap'
|
6
|
+
|
7
|
+
module Mu
|
8
|
+
class Scenario
|
9
|
+
module Pcap
|
10
|
+
|
11
|
+
class Fields
|
12
|
+
FIELDS = [
|
13
|
+
:rtp,
|
14
|
+
:"rtp.setup-frame"
|
15
|
+
].freeze
|
16
|
+
FIELD_COUNT = FIELDS.length
|
17
|
+
SEPARATOR = "\xff".freeze
|
18
|
+
TSHARK_OPTS = "-Eseparator='#{SEPARATOR}'"
|
19
|
+
FIELDS.each do |field|
|
20
|
+
TSHARK_OPTS << " -e #{field}"
|
21
|
+
end
|
22
|
+
TSHARK_OPTS.freeze
|
23
|
+
|
24
|
+
def self.readline io
|
25
|
+
if ::IO.select [ io ], nil, nil, Pcap::TSHARK_READ_TIMEOUT
|
26
|
+
return io.readline.chomp
|
27
|
+
end
|
28
|
+
|
29
|
+
raise Errno::ETIMEDOUT, "read timed out"
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.next_from_io io
|
33
|
+
if line = readline(io)
|
34
|
+
fields = line.split SEPARATOR, FIELD_COUNT
|
35
|
+
hash = {}
|
36
|
+
FIELDS.each do |key|
|
37
|
+
val = fields.shift
|
38
|
+
hash[key] = val.empty? ? nil : val
|
39
|
+
end
|
40
|
+
return hash
|
41
|
+
end
|
42
|
+
rescue Exception => e
|
43
|
+
Pcap.warning e.message
|
44
|
+
return nil
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -1,71 +1,71 @@
|
|
1
|
-
# http://www.mudynamics.com
|
2
|
-
# http://labs.mudynamics.com
|
3
|
-
# http://www.pcapr.net
|
4
|
-
|
5
|
-
module Mu
|
6
|
-
class Scenario
|
7
|
-
module Pcap
|
8
|
-
module Rtp
|
9
|
-
|
10
|
-
TRUNC_COUNT = 5
|
11
|
-
|
12
|
-
def self.preprocess packets, fields_per_packet
|
13
|
-
signaled_by = []
|
14
|
-
prev_signal_frame = {}
|
15
|
-
packets.each_with_index do |packet, idx|
|
16
|
-
fields = fields_per_packet[idx]
|
17
|
-
if fields and fields[:rtp]
|
18
|
-
flow_id = packet.flow_id
|
19
|
-
if frame = fields[:"rtp.setup-frame"]
|
20
|
-
prev_signal_frame[flow_id] = frame
|
21
|
-
else
|
22
|
-
if frame = prev_signal_frame[flow_id]
|
23
|
-
fields[:"rtp.setup-frame"] = frame
|
24
|
-
else
|
25
|
-
packets[idx] = nil
|
26
|
-
fields_per_packet[idx] = nil
|
27
|
-
next
|
28
|
-
end
|
29
|
-
end
|
30
|
-
sig_idx = frame.to_i
|
31
|
-
signaled_by[idx] = sig_idx
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
flow_to_count = Hash.new 0
|
36
|
-
prev_setup_frame = {}
|
37
|
-
keep_frames = []
|
38
|
-
packets.each_with_index do |packet, idx|
|
39
|
-
if setup_frame = signaled_by[idx]
|
40
|
-
flow = packet.flow_id
|
41
|
-
count = flow_to_count[flow]
|
42
|
-
if setup_frame != prev_setup_frame[flow]
|
43
|
-
prev_setup_frame[flow] = setup_frame
|
44
|
-
count = 1
|
45
|
-
else
|
46
|
-
count += 1
|
47
|
-
end
|
48
|
-
if count <= TRUNC_COUNT
|
49
|
-
keep_frames << idx + 1
|
50
|
-
else
|
51
|
-
packets[idx] = nil
|
52
|
-
fields_per_packet[idx] = nil
|
53
|
-
end
|
54
|
-
flow_to_count[flow] = count
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
packets.reject! {|p| not p }
|
59
|
-
fields_per_packet.reject! {|p| not p }
|
60
|
-
|
61
|
-
filter = "not rtp"
|
62
|
-
keep_frames.each do |frame|
|
63
|
-
filter << " or frame.number == #{frame}"
|
64
|
-
end
|
65
|
-
|
66
|
-
return filter
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
1
|
+
# http://www.mudynamics.com
|
2
|
+
# http://labs.mudynamics.com
|
3
|
+
# http://www.pcapr.net
|
4
|
+
|
5
|
+
module Mu
|
6
|
+
class Scenario
|
7
|
+
module Pcap
|
8
|
+
module Rtp
|
9
|
+
|
10
|
+
TRUNC_COUNT = 5
|
11
|
+
|
12
|
+
def self.preprocess packets, fields_per_packet
|
13
|
+
signaled_by = []
|
14
|
+
prev_signal_frame = {}
|
15
|
+
packets.each_with_index do |packet, idx|
|
16
|
+
fields = fields_per_packet[idx]
|
17
|
+
if fields and fields[:rtp]
|
18
|
+
flow_id = packet.flow_id
|
19
|
+
if frame = fields[:"rtp.setup-frame"]
|
20
|
+
prev_signal_frame[flow_id] = frame
|
21
|
+
else
|
22
|
+
if frame = prev_signal_frame[flow_id]
|
23
|
+
fields[:"rtp.setup-frame"] = frame
|
24
|
+
else
|
25
|
+
packets[idx] = nil
|
26
|
+
fields_per_packet[idx] = nil
|
27
|
+
next
|
28
|
+
end
|
29
|
+
end
|
30
|
+
sig_idx = frame.to_i
|
31
|
+
signaled_by[idx] = sig_idx
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
flow_to_count = Hash.new 0
|
36
|
+
prev_setup_frame = {}
|
37
|
+
keep_frames = []
|
38
|
+
packets.each_with_index do |packet, idx|
|
39
|
+
if setup_frame = signaled_by[idx]
|
40
|
+
flow = packet.flow_id
|
41
|
+
count = flow_to_count[flow]
|
42
|
+
if setup_frame != prev_setup_frame[flow]
|
43
|
+
prev_setup_frame[flow] = setup_frame
|
44
|
+
count = 1
|
45
|
+
else
|
46
|
+
count += 1
|
47
|
+
end
|
48
|
+
if count <= TRUNC_COUNT
|
49
|
+
keep_frames << idx + 1
|
50
|
+
else
|
51
|
+
packets[idx] = nil
|
52
|
+
fields_per_packet[idx] = nil
|
53
|
+
end
|
54
|
+
flow_to_count[flow] = count
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
packets.reject! {|p| not p }
|
59
|
+
fields_per_packet.reject! {|p| not p }
|
60
|
+
|
61
|
+
filter = "not rtp"
|
62
|
+
keep_frames.each do |frame|
|
63
|
+
filter << " or frame.number == #{frame}"
|
64
|
+
end
|
65
|
+
|
66
|
+
return filter
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/diy/parser/pcap.rb
CHANGED
@@ -1,113 +1,113 @@
|
|
1
|
-
# http://www.mudynamics.com
|
2
|
-
# http://labs.mudynamics.com
|
1
|
+
# http://www.mudynamics.com
|
2
|
+
# http://labs.mudynamics.com
|
3
3
|
# http://www.pcapr.net
|
4
4
|
|
5
5
|
$LOAD_PATH.unshift File.dirname(__FILE__)
|
6
|
-
|
7
|
-
require 'socket'
|
6
|
+
|
7
|
+
require 'socket'
|
8
8
|
require 'stringio'
|
9
|
-
require 'mu/fixnum_ext'
|
10
|
-
|
11
|
-
module Mu
|
12
|
-
|
13
|
-
class Pcap
|
14
|
-
class ParseError < StandardError ; end
|
15
|
-
|
16
|
-
LITTLE_ENDIAN = 0xd4c3b2a1
|
17
|
-
BIG_ENDIAN = 0xa1b2c3d4
|
18
|
-
|
19
|
-
DLT_NULL = 0
|
20
|
-
DLT_EN10MB = 1
|
21
|
-
DLT_RAW = 12 # DLT_LOOP in OpenBSD
|
22
|
-
DLT_LINUX_SLL = 113
|
23
|
-
|
24
|
-
attr_accessor :header, :pkthdrs
|
25
|
-
|
26
|
-
def initialize
|
27
|
-
@header = Header.new
|
28
|
-
@pkthdrs = []
|
29
|
-
end
|
30
|
-
|
31
|
-
# Read PCAP file from IO and return Mu::Pcap. If decode is true, also
|
32
|
-
# decode the Pkthdr packet contents to Mu::Pcap objects.
|
33
|
-
def self.read io, decode=true
|
34
|
-
pcap = Pcap.new
|
35
|
-
pcap.header = each_pkthdr(io, decode) do |pkthdr|
|
36
|
-
pcap.pkthdrs << pkthdr
|
37
|
-
end
|
38
|
-
return pcap
|
39
|
-
end
|
40
|
-
|
41
|
-
# Create PCAP from list of packets.
|
42
|
-
def self.from_packets packets
|
43
|
-
pcap = Pcap.new
|
44
|
-
packets.each do |packet|
|
45
|
-
pkthdr = Mu::Pcap::Pkthdr.new
|
46
|
-
pkthdr.pkt = packet
|
47
|
-
pcap.pkthdrs << pkthdr
|
48
|
-
end
|
49
|
-
return pcap
|
50
|
-
end
|
51
|
-
|
52
|
-
# Write PCAP file to IO. Uses big-endian and linktype EN10MB.
|
53
|
-
def write io
|
54
|
-
@header.write io
|
55
|
-
@pkthdrs.each do |pkthdr|
|
56
|
-
pkthdr.write io
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
# Read PCAP packet headers from IO and return Mu::Pcap::Header. If decode
|
61
|
-
# is true, also decode the Pkthdr packet contents to Mu::Pcap objects. Use
|
62
|
-
# this for large files when each packet header can processed independently
|
63
|
-
# - it will perform better.
|
64
|
-
def self.each_pkthdr io, decode=true
|
65
|
-
header = Header.read io
|
66
|
-
while not io.eof?
|
67
|
-
pkthdr = Pkthdr.read io, header.magic
|
68
|
-
if decode
|
69
|
-
pkthdr.decode! header.magic, header.linktype
|
70
|
-
end
|
71
|
-
yield pkthdr
|
72
|
-
end
|
73
|
-
return header
|
74
|
-
end
|
75
|
-
|
76
|
-
# Read packets from PCAP
|
77
|
-
def self.read_packets io, decode=true
|
78
|
-
packets = []
|
79
|
-
each_pkthdr(io) { |pkthdr| packets << pkthdr.pkt }
|
80
|
-
return packets
|
81
|
-
end
|
82
|
-
|
83
|
-
# Assertion used during Pcap parsing
|
84
|
-
def self.assert cond, msg
|
85
|
-
if not cond
|
86
|
-
raise ParseError, msg
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
# Warnings from Pcap parsing are printed using this method.
|
91
|
-
def self.warning msg
|
92
|
-
$stderr.puts "WARNING: #{msg}"
|
93
|
-
end
|
94
|
-
|
95
|
-
def == other
|
96
|
-
return self.class == other.class &&
|
97
|
-
self.header == other.header &&
|
98
|
-
self.pkthdrs == other.pkthdrs
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
end
|
103
|
-
|
104
|
-
require 'mu/pcap/header'
|
105
|
-
require 'mu/pcap/pkthdr'
|
106
|
-
require 'mu/pcap/packet'
|
107
|
-
require 'mu/pcap/ethernet'
|
108
|
-
require 'mu/pcap/ip'
|
109
|
-
require 'mu/pcap/ipv4'
|
110
|
-
require 'mu/pcap/ipv6'
|
111
|
-
require 'mu/pcap/tcp'
|
112
|
-
require 'mu/pcap/udp'
|
113
|
-
require 'mu/pcap/sctp'
|
9
|
+
require 'mu/fixnum_ext'
|
10
|
+
|
11
|
+
module Mu
|
12
|
+
|
13
|
+
class Pcap
|
14
|
+
class ParseError < StandardError ; end
|
15
|
+
|
16
|
+
LITTLE_ENDIAN = 0xd4c3b2a1
|
17
|
+
BIG_ENDIAN = 0xa1b2c3d4
|
18
|
+
|
19
|
+
DLT_NULL = 0
|
20
|
+
DLT_EN10MB = 1
|
21
|
+
DLT_RAW = 12 # DLT_LOOP in OpenBSD
|
22
|
+
DLT_LINUX_SLL = 113
|
23
|
+
|
24
|
+
attr_accessor :header, :pkthdrs
|
25
|
+
|
26
|
+
def initialize
|
27
|
+
@header = Header.new
|
28
|
+
@pkthdrs = []
|
29
|
+
end
|
30
|
+
|
31
|
+
# Read PCAP file from IO and return Mu::Pcap. If decode is true, also
|
32
|
+
# decode the Pkthdr packet contents to Mu::Pcap objects.
|
33
|
+
def self.read io, decode=true
|
34
|
+
pcap = Pcap.new
|
35
|
+
pcap.header = each_pkthdr(io, decode) do |pkthdr|
|
36
|
+
pcap.pkthdrs << pkthdr
|
37
|
+
end
|
38
|
+
return pcap
|
39
|
+
end
|
40
|
+
|
41
|
+
# Create PCAP from list of packets.
|
42
|
+
def self.from_packets packets
|
43
|
+
pcap = Pcap.new
|
44
|
+
packets.each do |packet|
|
45
|
+
pkthdr = Mu::Pcap::Pkthdr.new
|
46
|
+
pkthdr.pkt = packet
|
47
|
+
pcap.pkthdrs << pkthdr
|
48
|
+
end
|
49
|
+
return pcap
|
50
|
+
end
|
51
|
+
|
52
|
+
# Write PCAP file to IO. Uses big-endian and linktype EN10MB.
|
53
|
+
def write io
|
54
|
+
@header.write io
|
55
|
+
@pkthdrs.each do |pkthdr|
|
56
|
+
pkthdr.write io
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Read PCAP packet headers from IO and return Mu::Pcap::Header. If decode
|
61
|
+
# is true, also decode the Pkthdr packet contents to Mu::Pcap objects. Use
|
62
|
+
# this for large files when each packet header can processed independently
|
63
|
+
# - it will perform better.
|
64
|
+
def self.each_pkthdr io, decode=true
|
65
|
+
header = Header.read io
|
66
|
+
while not io.eof?
|
67
|
+
pkthdr = Pkthdr.read io, header.magic
|
68
|
+
if decode
|
69
|
+
pkthdr.decode! header.magic, header.linktype
|
70
|
+
end
|
71
|
+
yield pkthdr
|
72
|
+
end
|
73
|
+
return header
|
74
|
+
end
|
75
|
+
|
76
|
+
# Read packets from PCAP
|
77
|
+
def self.read_packets io, decode=true
|
78
|
+
packets = []
|
79
|
+
each_pkthdr(io) { |pkthdr| packets << pkthdr.pkt }
|
80
|
+
return packets
|
81
|
+
end
|
82
|
+
|
83
|
+
# Assertion used during Pcap parsing
|
84
|
+
def self.assert cond, msg
|
85
|
+
if not cond
|
86
|
+
raise ParseError, msg
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# Warnings from Pcap parsing are printed using this method.
|
91
|
+
def self.warning msg
|
92
|
+
$stderr.puts "WARNING: #{msg}"
|
93
|
+
end
|
94
|
+
|
95
|
+
def == other
|
96
|
+
return self.class == other.class &&
|
97
|
+
self.header == other.header &&
|
98
|
+
self.pkthdrs == other.pkthdrs
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
require 'mu/pcap/header'
|
105
|
+
require 'mu/pcap/pkthdr'
|
106
|
+
require 'mu/pcap/packet'
|
107
|
+
require 'mu/pcap/ethernet'
|
108
|
+
require 'mu/pcap/ip'
|
109
|
+
require 'mu/pcap/ipv4'
|
110
|
+
require 'mu/pcap/ipv6'
|
111
|
+
require 'mu/pcap/tcp'
|
112
|
+
require 'mu/pcap/udp'
|
113
|
+
require 'mu/pcap/sctp'
|