DIY-pcap 0.4.1 → 0.4.3
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/.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'
|