pcapr-local 0.1.10
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/.document +5 -0
- data/LICENSE.txt +20 -0
- data/README.md +64 -0
- data/Rakefile +57 -0
- data/VERSION +1 -0
- data/bin/pcap2par +49 -0
- data/bin/startpcapr +40 -0
- data/bin/stoppcapr +33 -0
- data/bin/xtractr +5 -0
- data/lib/environment.rb +106 -0
- data/lib/exe/xtractr +0 -0
- data/lib/mu/pcap.rb +110 -0
- data/lib/mu/pcap/ethernet.rb +148 -0
- data/lib/mu/pcap/header.rb +75 -0
- data/lib/mu/pcap/io_pair.rb +67 -0
- data/lib/mu/pcap/io_wrapper.rb +76 -0
- data/lib/mu/pcap/ip.rb +61 -0
- data/lib/mu/pcap/ipv4.rb +257 -0
- data/lib/mu/pcap/ipv6.rb +148 -0
- data/lib/mu/pcap/packet.rb +104 -0
- data/lib/mu/pcap/pkthdr.rb +155 -0
- data/lib/mu/pcap/reader.rb +61 -0
- data/lib/mu/pcap/reader/http_family.rb +170 -0
- data/lib/mu/pcap/sctp.rb +367 -0
- data/lib/mu/pcap/sctp/chunk.rb +123 -0
- data/lib/mu/pcap/sctp/chunk/data.rb +134 -0
- data/lib/mu/pcap/sctp/chunk/init.rb +100 -0
- data/lib/mu/pcap/sctp/chunk/init_ack.rb +68 -0
- data/lib/mu/pcap/sctp/parameter.rb +110 -0
- data/lib/mu/pcap/sctp/parameter/ip_address.rb +48 -0
- data/lib/mu/pcap/stream_packetizer.rb +72 -0
- data/lib/mu/pcap/tcp.rb +505 -0
- data/lib/mu/pcap/udp.rb +69 -0
- data/lib/mu/scenario/pcap.rb +164 -0
- data/lib/mu/scenario/pcap/fields.rb +50 -0
- data/lib/mu/scenario/pcap/rtp.rb +71 -0
- data/lib/pcapr_local.rb +159 -0
- data/lib/pcapr_local/config.rb +336 -0
- data/lib/pcapr_local/db.rb +197 -0
- data/lib/pcapr_local/scanner.rb +250 -0
- data/lib/pcapr_local/server.rb +178 -0
- data/lib/pcapr_local/www/favicon.ico +0 -0
- data/lib/pcapr_local/www/favicon.png +0 -0
- data/lib/pcapr_local/www/home/index.html +138 -0
- data/lib/pcapr_local/www/static/image/16x16/Cancel.png +0 -0
- data/lib/pcapr_local/www/static/image/16x16/Cancel.png.1 +0 -0
- data/lib/pcapr_local/www/static/image/16x16/Download.png +0 -0
- data/lib/pcapr_local/www/static/image/16x16/Folder3.png +0 -0
- data/lib/pcapr_local/www/static/image/16x16/Full Size.png +0 -0
- data/lib/pcapr_local/www/static/image/16x16/Minus.png +0 -0
- data/lib/pcapr_local/www/static/image/16x16/Plus.png +0 -0
- data/lib/pcapr_local/www/static/image/16x16/Search.png +0 -0
- data/lib/pcapr_local/www/static/image/16x16/User.png +0 -0
- data/lib/pcapr_local/www/static/image/48x48/Phone.png +0 -0
- data/lib/pcapr_local/www/static/image/48x48/Video.png +0 -0
- data/lib/pcapr_local/www/static/image/bar-orange.gif +0 -0
- data/lib/pcapr_local/www/static/image/beta.png +0 -0
- data/lib/pcapr_local/www/static/image/bg.png +0 -0
- data/lib/pcapr_local/www/static/image/blockquote.png +0 -0
- data/lib/pcapr_local/www/static/image/body-bg.png +0 -0
- data/lib/pcapr_local/www/static/image/body-h3.png +0 -0
- data/lib/pcapr_local/www/static/image/body-hl1-bg.png +0 -0
- data/lib/pcapr_local/www/static/image/body-hl1-h3.png +0 -0
- data/lib/pcapr_local/www/static/image/body-hl1-readmore.png +0 -0
- data/lib/pcapr_local/www/static/image/body-hl2-bg.png +0 -0
- data/lib/pcapr_local/www/static/image/body-hl2-h3.png +0 -0
- data/lib/pcapr_local/www/static/image/body-hl2-readmore.png +0 -0
- data/lib/pcapr_local/www/static/image/body-hl3-bg.png +0 -0
- data/lib/pcapr_local/www/static/image/body-hl3-h3.png +0 -0
- data/lib/pcapr_local/www/static/image/body-hl3-readmore.png +0 -0
- data/lib/pcapr_local/www/static/image/body-hl4-bg.png +0 -0
- data/lib/pcapr_local/www/static/image/body-hl4-h3.png +0 -0
- data/lib/pcapr_local/www/static/image/body-hl4-readmore.png +0 -0
- data/lib/pcapr_local/www/static/image/body-hl5-h3.png +0 -0
- data/lib/pcapr_local/www/static/image/body-hl6-h3.png +0 -0
- data/lib/pcapr_local/www/static/image/body-hl7-h3.png +0 -0
- data/lib/pcapr_local/www/static/image/body-hl8-h3.png +0 -0
- data/lib/pcapr_local/www/static/image/body-readmore.png +0 -0
- data/lib/pcapr_local/www/static/image/bottom-bg.png +0 -0
- data/lib/pcapr_local/www/static/image/bottom-l.png +0 -0
- data/lib/pcapr_local/www/static/image/bottom-r.png +0 -0
- data/lib/pcapr_local/www/static/image/btn-search.png +0 -0
- data/lib/pcapr_local/www/static/image/bullet-1.png +0 -0
- data/lib/pcapr_local/www/static/image/bullet-2.png +0 -0
- data/lib/pcapr_local/www/static/image/bullet-3.png +0 -0
- data/lib/pcapr_local/www/static/image/bullet-4.png +0 -0
- data/lib/pcapr_local/www/static/image/bullet-5.png +0 -0
- data/lib/pcapr_local/www/static/image/bullet-6.png +0 -0
- data/lib/pcapr_local/www/static/image/bullet-7.png +0 -0
- data/lib/pcapr_local/www/static/image/bullet-hl1.png +0 -0
- data/lib/pcapr_local/www/static/image/bullet-hl2.png +0 -0
- data/lib/pcapr_local/www/static/image/bullet-hl3.png +0 -0
- data/lib/pcapr_local/www/static/image/bullet-hl4.png +0 -0
- data/lib/pcapr_local/www/static/image/bullet-pathway.png +0 -0
- data/lib/pcapr_local/www/static/image/bullet-section1.png +0 -0
- data/lib/pcapr_local/www/static/image/bullet-section2.png +0 -0
- data/lib/pcapr_local/www/static/image/collapsed.gif +0 -0
- data/lib/pcapr_local/www/static/image/crosslink.png +0 -0
- data/lib/pcapr_local/www/static/image/expanded.gif +0 -0
- data/lib/pcapr_local/www/static/image/favicon.ico +0 -0
- data/lib/pcapr_local/www/static/image/favicon.png +0 -0
- data/lib/pcapr_local/www/static/image/icon-author.png +0 -0
- data/lib/pcapr_local/www/static/image/icon-created.png +0 -0
- data/lib/pcapr_local/www/static/image/p-expand.gif +0 -0
- data/lib/pcapr_local/www/static/image/pcapr-logo.png +0 -0
- data/lib/pcapr_local/www/static/image/powered-by.png +0 -0
- data/lib/pcapr_local/www/static/image/section1-bg.png +0 -0
- data/lib/pcapr_local/www/static/image/section1-h3.png +0 -0
- data/lib/pcapr_local/www/static/image/section1-readmore.png +0 -0
- data/lib/pcapr_local/www/static/image/section2-bg.png +0 -0
- data/lib/pcapr_local/www/static/image/section2-h3.png +0 -0
- data/lib/pcapr_local/www/static/image/section2-readmore.png +0 -0
- data/lib/pcapr_local/www/static/image/status-alert.png +0 -0
- data/lib/pcapr_local/www/static/image/status-download.png +0 -0
- data/lib/pcapr_local/www/static/image/status-info.png +0 -0
- data/lib/pcapr_local/www/static/image/status-note.png +0 -0
- data/lib/pcapr_local/www/static/image/tab-round.png +0 -0
- data/lib/pcapr_local/www/static/image/throbber.gif +0 -0
- data/lib/pcapr_local/www/static/image/user.jpg +0 -0
- data/lib/pcapr_local/www/static/script/closet/async.js +421 -0
- data/lib/pcapr_local/www/static/script/closet/closet.api.js +241 -0
- data/lib/pcapr_local/www/static/script/closet/closet.folders.js +94 -0
- data/lib/pcapr_local/www/static/script/closet/closet.js +187 -0
- data/lib/pcapr_local/www/static/script/closet/closet.mr.js +219 -0
- data/lib/pcapr_local/www/static/script/closet/closet.options.js +359 -0
- data/lib/pcapr_local/www/static/script/closet/closet.quantity.js +73 -0
- data/lib/pcapr_local/www/static/script/closet/closet.render.js +205 -0
- data/lib/pcapr_local/www/static/script/closet/closet.report.js +86 -0
- data/lib/pcapr_local/www/static/script/closet/closet.reports.http.js +135 -0
- data/lib/pcapr_local/www/static/script/closet/closet.reports.overview.js +163 -0
- data/lib/pcapr_local/www/static/script/closet/closet.reports.sip.js +159 -0
- data/lib/pcapr_local/www/static/script/closet/closet.reports.tcp.js +72 -0
- data/lib/pcapr_local/www/static/script/closet/closet.reports.visualize.js +263 -0
- data/lib/pcapr_local/www/static/script/closet/closet.util.js +40 -0
- data/lib/pcapr_local/www/static/script/jquery/jquery-1.4.2.min.js +154 -0
- data/lib/pcapr_local/www/static/script/jquery/jquery-ui.js +10921 -0
- data/lib/pcapr_local/www/static/script/jquery/jquery.flot.js +2123 -0
- data/lib/pcapr_local/www/static/script/jquery/jquery.flot.selection.js +184 -0
- data/lib/pcapr_local/www/static/script/jquery/jquery.flot.stack.js +184 -0
- data/lib/pcapr_local/www/static/script/jquery/jquery.form.js +643 -0
- data/lib/pcapr_local/www/static/script/jquery/jquery.jsonp.min.js +3 -0
- data/lib/pcapr_local/www/static/script/jquery/jquery.menu.js +142 -0
- data/lib/pcapr_local/www/static/script/jquery/jquery.suggest.js +308 -0
- data/lib/pcapr_local/www/static/script/jquery/jquery.ui.core.js +203 -0
- data/lib/pcapr_local/www/static/script/jquery/jquery.ui.slider.js +629 -0
- data/lib/pcapr_local/www/static/script/jquery/jquery.ui.sortable.js +1055 -0
- data/lib/pcapr_local/www/static/script/jquery/jquery.ui.widget.js +236 -0
- data/lib/pcapr_local/www/static/script/json2.js +481 -0
- data/lib/pcapr_local/www/static/script/sammy/plugins/sammy.cache.js +115 -0
- data/lib/pcapr_local/www/static/script/sammy/plugins/sammy.template.js +117 -0
- data/lib/pcapr_local/www/static/script/sammy/sammy.js +1696 -0
- data/lib/pcapr_local/www/static/script/tipsy/jquery.tipsy.js +104 -0
- data/lib/pcapr_local/www/static/style/c3p0.css +116 -0
- data/lib/pcapr_local/www/static/style/jquery.suggest.css +27 -0
- data/lib/pcapr_local/www/static/style/page.css +1113 -0
- data/lib/pcapr_local/www/static/style/tipsy.css +7 -0
- data/lib/pcapr_local/www/templates/browse.services.template +10 -0
- data/lib/pcapr_local/www/templates/browse.template +77 -0
- data/lib/pcapr_local/www/templates/flows.template +38 -0
- data/lib/pcapr_local/www/templates/pcap.template +63 -0
- data/lib/pcapr_local/www/templates/sip.calls.template +35 -0
- data/lib/pcapr_local/www/templates/statistics.template +6 -0
- data/lib/pcapr_local/xtractr.rb +179 -0
- data/lib/pcapr_local/xtractr/instance.rb +172 -0
- data/pcapr-local.gemspec +297 -0
- data/test/mu/pcap/reader/tc_http_family.rb +251 -0
- data/test/mu/pcap/tc_ethernet.rb +71 -0
- data/test/mu/pcap/tc_header.rb +56 -0
- data/test/mu/pcap/tc_ipv4.rb +103 -0
- data/test/mu/pcap/tc_ipv6.rb +83 -0
- data/test/mu/pcap/tc_packet.rb +44 -0
- data/test/mu/pcap/tc_pair.rb +58 -0
- data/test/mu/pcap/tc_pkthdr.rb +33 -0
- data/test/mu/pcap/tc_reader.rb +76 -0
- data/test/mu/pcap/tc_tcp.rb +426 -0
- data/test/mu/pcap/tc_udp.rb +33 -0
- data/test/mu/pcap/tc_wrapper.rb +80 -0
- data/test/mu/scenario/pcap/tc_fields.rb +67 -0
- data/test/mu/scenario/pcap/tc_rtp.rb +135 -0
- data/test/mu/scenario/sip_signalled_call_1.pcap +0 -0
- data/test/mu/scenario/tc_pcap.rb +190 -0
- data/test/mu/scenario/test_data/arp.pcap +0 -0
- data/test/mu/scenario/test_data/dns.pcap +0 -0
- data/test/mu/scenario/test_data/http-v6.pcap +0 -0
- data/test/mu/scenario/test_data/http.pcap +0 -0
- data/test/mu/scenario/test_data/http_chunked.pcap +0 -0
- data/test/mu/scenario/test_data/http_deflate.pcap +0 -0
- data/test/mu/scenario/test_data/httpauth3.pcap +0 -0
- data/test/mu/scenario/test_data/icmp.pcap +0 -0
- data/test/mu/scenario/test_data/sip_signalled_call_1.pcap +0 -0
- data/test/mu/tc_pcap.rb +39 -0
- data/test/mu/testcase.rb +86 -0
- data/test/pcapr_local/arp.pcap +0 -0
- data/test/pcapr_local/data.js +3 -0
- data/test/pcapr_local/http_chunked.pcap +0 -0
- data/test/pcapr_local/tc_api.rb +181 -0
- data/test/pcapr_local/test.tgz +0 -0
- data/test/pcapr_local/test_scanner.rb +241 -0
- data/test/pcapr_local/test_xtractr.rb +219 -0
- data/test/pcapr_local/testcase.rb +107 -0
- data/test/test_export_to_scenario.sh +25 -0
- data/test/test_pcapr_local.rb +29 -0
- metadata +450 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# http://www.mudynamics.com
|
|
2
|
+
# http://labs.mudynamics.com
|
|
3
|
+
# http://www.pcapr.net
|
|
4
|
+
|
|
5
|
+
require 'mu/testcase'
|
|
6
|
+
require 'mu/pcap'
|
|
7
|
+
|
|
8
|
+
module Mu
|
|
9
|
+
class Pcap
|
|
10
|
+
class UDP
|
|
11
|
+
|
|
12
|
+
class Test < Mu::TestCase
|
|
13
|
+
def test_basics
|
|
14
|
+
udp = UDP.new
|
|
15
|
+
udp.src_port = 0x3039
|
|
16
|
+
udp.dst_port = 0x0050
|
|
17
|
+
udp.payload = 'hello'
|
|
18
|
+
udp.payload_raw = 'hello'
|
|
19
|
+
|
|
20
|
+
bytes =
|
|
21
|
+
"\x30\x39" + # src port
|
|
22
|
+
"\x00\x50" + # dst port
|
|
23
|
+
"\x00\x0d" + # length
|
|
24
|
+
"\x00\x00" + # checksum
|
|
25
|
+
'hello'
|
|
26
|
+
udp_in = UDP.from_bytes bytes
|
|
27
|
+
assert_equal udp_in, udp
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# http://www.mudynamics.com
|
|
2
|
+
# http://labs.mudynamics.com
|
|
3
|
+
# http://www.pcapr.net
|
|
4
|
+
|
|
5
|
+
require 'mu/testcase'
|
|
6
|
+
require 'mu/pcap/io_wrapper'
|
|
7
|
+
require 'mu/pcap/io_pair'
|
|
8
|
+
|
|
9
|
+
module Mu
|
|
10
|
+
class Pcap
|
|
11
|
+
class IOWrapper
|
|
12
|
+
class Test < Mu::TestCase
|
|
13
|
+
class MessageReader
|
|
14
|
+
def initialize msg_size=10
|
|
15
|
+
@msg_size = msg_size
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def read_message! bytes, state
|
|
19
|
+
state[:bytes_read] ||= 0
|
|
20
|
+
if bytes.length >= @msg_size
|
|
21
|
+
msg = bytes.slice!(0,@msg_size)
|
|
22
|
+
msg.upcase!
|
|
23
|
+
state[:bytes_read] += @msg_size
|
|
24
|
+
end
|
|
25
|
+
msg
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def record_write bytes, state
|
|
29
|
+
state[:bytes_sent] ||= 0
|
|
30
|
+
state[:bytes_sent] += bytes.size
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def test_basics
|
|
35
|
+
inner, other = IOPair.stream_pair
|
|
36
|
+
wrapped = IOWrapper.new inner, MessageReader.new
|
|
37
|
+
|
|
38
|
+
# Reads
|
|
39
|
+
other.write "01234567890123"
|
|
40
|
+
assert_equal "", wrapped.unread
|
|
41
|
+
assert_equal "0123456789", wrapped.read
|
|
42
|
+
assert_equal "0123", wrapped.unread
|
|
43
|
+
assert_equal 10, wrapped.state[:bytes_read]
|
|
44
|
+
assert_nil wrapped.read
|
|
45
|
+
other.write "456789"
|
|
46
|
+
assert_equal "0123456789", wrapped.read
|
|
47
|
+
assert_equal "", wrapped.unread
|
|
48
|
+
assert_equal 20, wrapped.state[:bytes_read]
|
|
49
|
+
other.write "abcdefghij"
|
|
50
|
+
assert_equal "ABCDEFGHIJ", wrapped.read
|
|
51
|
+
assert_equal 30, wrapped.state[:bytes_read]
|
|
52
|
+
|
|
53
|
+
# Writes
|
|
54
|
+
wrapped.write "hi mom"
|
|
55
|
+
assert_equal 6, wrapped.state[:bytes_sent]
|
|
56
|
+
assert_equal "hi mom", other.read
|
|
57
|
+
assert_equal "", other.read
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def test_too_big_receive
|
|
61
|
+
# Message at max size.
|
|
62
|
+
inner, other = IOPair.stream_pair
|
|
63
|
+
wrapped = IOWrapper.new inner, MessageReader.new(MAX_RECEIVE_SIZE + 2)
|
|
64
|
+
big = "a" * MAX_RECEIVE_SIZE
|
|
65
|
+
other.write big
|
|
66
|
+
wrapped.read
|
|
67
|
+
|
|
68
|
+
# Message over max size.
|
|
69
|
+
too_big = big + "1"
|
|
70
|
+
other.write too_big
|
|
71
|
+
e = assert_raises(RuntimeError) do
|
|
72
|
+
wrapped.read
|
|
73
|
+
end
|
|
74
|
+
assert_match "Maximum message size (#{MAX_RECEIVE_SIZE}) exceeded", e.message
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# http://www.mudynamics.com
|
|
2
|
+
# http://labs.mudynamics.com
|
|
3
|
+
# http://www.pcapr.net
|
|
4
|
+
|
|
5
|
+
require 'mu/testcase'
|
|
6
|
+
require 'mu/scenario/pcap/fields'
|
|
7
|
+
|
|
8
|
+
module Mu
|
|
9
|
+
class Scenario
|
|
10
|
+
module Pcap
|
|
11
|
+
class Fields
|
|
12
|
+
|
|
13
|
+
class Test < Mu::TestCase
|
|
14
|
+
TFIELDS_DATA = <<EOF
|
|
15
|
+
pale ale\xffkobe burger\xffmayo
|
|
16
|
+
milk shake\xffsundae\xffwhipped cream
|
|
17
|
+
\xff\xff
|
|
18
|
+
EOF
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def test_basics
|
|
22
|
+
fields_save = FIELDS
|
|
23
|
+
field_count_save = FIELD_COUNT
|
|
24
|
+
Fields.const_set! :FIELDS, [:"meal.drink", :"meal.entre", :"meal.side"]
|
|
25
|
+
Fields.const_set! :FIELD_COUNT, 3
|
|
26
|
+
|
|
27
|
+
read, write = ::IO.pipe
|
|
28
|
+
write.print TFIELDS_DATA
|
|
29
|
+
|
|
30
|
+
fields1 = Fields.next_from_io read
|
|
31
|
+
assert_equal 3, fields1.length
|
|
32
|
+
assert_equal "pale ale", fields1[:"meal.drink"]
|
|
33
|
+
|
|
34
|
+
fields2 = Fields.next_from_io read
|
|
35
|
+
assert_equal 3, fields2.length
|
|
36
|
+
assert_equal "sundae", fields2[:"meal.entre"]
|
|
37
|
+
assert_equal "whipped cream", fields2[:"meal.side"]
|
|
38
|
+
|
|
39
|
+
# nil for empty fields
|
|
40
|
+
fields3 = Fields.next_from_io read
|
|
41
|
+
assert_equal 3, fields3.length
|
|
42
|
+
assert_nil fields3[:"meal.drink"]
|
|
43
|
+
assert_nil fields3[:"meal.entre"]
|
|
44
|
+
assert_nil fields3[:"meal.side"]
|
|
45
|
+
|
|
46
|
+
# nil on timeout
|
|
47
|
+
begin
|
|
48
|
+
timeout_save = Pcap.const_get :TSHARK_READ_TIMEOUT
|
|
49
|
+
Pcap.const_set! :TSHARK_READ_TIMEOUT, 0.1
|
|
50
|
+
assert_nil Fields.next_from_io(read)
|
|
51
|
+
ensure
|
|
52
|
+
Pcap.const_set! :TSHARK_READ_TIMEOUT, timeout_save
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# nil on EOFError
|
|
56
|
+
write.close
|
|
57
|
+
assert_nil Fields.next_from_io(read)
|
|
58
|
+
ensure
|
|
59
|
+
Fields.const_set! :FIELDS, fields_save if fields_save
|
|
60
|
+
Fields.const_set! :FIELD_COUNT, field_count_save if field_count_save
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# http://www.mudynamics.com
|
|
2
|
+
# http://labs.mudynamics.com
|
|
3
|
+
# http://www.pcapr.net
|
|
4
|
+
|
|
5
|
+
require 'mu/testcase'
|
|
6
|
+
require 'mu/scenario/pcap/rtp'
|
|
7
|
+
|
|
8
|
+
module Mu
|
|
9
|
+
class Scenario
|
|
10
|
+
module Pcap
|
|
11
|
+
module Rtp
|
|
12
|
+
|
|
13
|
+
class Test < Mu::TestCase
|
|
14
|
+
|
|
15
|
+
DATA = [
|
|
16
|
+
[[:udp, 1,2,3,4], {}],
|
|
17
|
+
[[:udp, 3,4,5,6], {:"rtp.setup-frame" => 1}]
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
Packet = ::Struct.new :flow_id
|
|
21
|
+
def gen_packets data
|
|
22
|
+
packets = []
|
|
23
|
+
fields_array = []
|
|
24
|
+
data.map do |flow_id, fields|
|
|
25
|
+
packets << Packet.new(flow_id)
|
|
26
|
+
fields_array << fields
|
|
27
|
+
end
|
|
28
|
+
return packets, fields_array
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def test_preprocess
|
|
32
|
+
trunc_count_save = Rtp::TRUNC_COUNT
|
|
33
|
+
Rtp.const_set! :TRUNC_COUNT, 5
|
|
34
|
+
# No truncation
|
|
35
|
+
packets, fields = gen_packets [
|
|
36
|
+
[[:udp, 1,2,3,4], {}],
|
|
37
|
+
[[:udp, 3,4,5,6], {:"rtp.setup-frame" => 1}],
|
|
38
|
+
[[:udp, 3,4,5,6], {:"rtp.setup-frame" => 1}],
|
|
39
|
+
[[:udp, 3,4,5,6], {:"rtp.setup-frame" => 1}],
|
|
40
|
+
[[:udp, 3,4,5,6], {:"rtp.setup-frame" => 1}],
|
|
41
|
+
[[:udp, 3,4,5,6], {:"rtp.setup-frame" => 1}],
|
|
42
|
+
]
|
|
43
|
+
filter = Rtp.preprocess packets, fields
|
|
44
|
+
assert_equal 6, packets.length
|
|
45
|
+
assert_equal "not rtp", filter
|
|
46
|
+
|
|
47
|
+
# Truncate stream
|
|
48
|
+
packets, fields = gen_packets [
|
|
49
|
+
[[:udp, 1,2,3,4], {}],
|
|
50
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp", :"rtp.setup-frame" => "1"}],
|
|
51
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp", :"rtp.setup-frame" => "1"}],
|
|
52
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp", :"rtp.setup-frame" => "1"}],
|
|
53
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp", :"rtp.setup-frame" => "1"}],
|
|
54
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp", :"rtp.setup-frame" => "1"}],
|
|
55
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp", :"rtp.setup-frame" => "1"}], #skip
|
|
56
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp", :"rtp.setup-frame" => "1"}], #skip
|
|
57
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp", :"rtp.setup-frame" => "1"}], #skip
|
|
58
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp", :"rtp.setup-frame" => "1"}], #skip
|
|
59
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp", :"rtp.setup-frame" => "1"}], #skip
|
|
60
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp", :"rtp.setup-frame" => "1"}], #skip
|
|
61
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp", :"rtp.setup-frame" => "1"}], #skip
|
|
62
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp", :"rtp.setup-frame" => "1"}], #skip
|
|
63
|
+
]
|
|
64
|
+
filter = Rtp.preprocess packets, fields
|
|
65
|
+
assert_equal TRUNC_COUNT + 1, packets.length
|
|
66
|
+
assert_equal TRUNC_COUNT + 1, fields.length
|
|
67
|
+
assert_equal "not rtp or frame.number == 2 or frame.number == 3 or frame.number == 4 or frame.number == 5 or frame.number == 6", filter
|
|
68
|
+
|
|
69
|
+
# Updated signaling resets truncation counter
|
|
70
|
+
packets, fields = gen_packets [
|
|
71
|
+
[[:udp, 1,2,3,4], {}],
|
|
72
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp", :"rtp.setup-frame" => "1"}],
|
|
73
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp", :"rtp.setup-frame" => "1"}],
|
|
74
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp", :"rtp.setup-frame" => "1"}],
|
|
75
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp", :"rtp.setup-frame" => "1"}],
|
|
76
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp", :"rtp.setup-frame" => "1"}],
|
|
77
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp", :"rtp.setup-frame" => "1"}], #skip
|
|
78
|
+
|
|
79
|
+
[[:udp, 1,2,3,4], {}],
|
|
80
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp", :"rtp.setup-frame" => "8"}],
|
|
81
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp", :"rtp.setup-frame" => "8"}],
|
|
82
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp", :"rtp.setup-frame" => "8"}],
|
|
83
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp", :"rtp.setup-frame" => "8"}],
|
|
84
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp", :"rtp.setup-frame" => "8"}],
|
|
85
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp", :"rtp.setup-frame" => "8"}], #skip
|
|
86
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp", :"rtp.setup-frame" => "8"}], #skip
|
|
87
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp", :"rtp.setup-frame" => "8"}], #skip
|
|
88
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp", :"rtp.setup-frame" => "8"}], #skip
|
|
89
|
+
]
|
|
90
|
+
filter = Rtp.preprocess packets, fields
|
|
91
|
+
assert_equal TRUNC_COUNT*2 + 2, packets.length
|
|
92
|
+
assert_equal TRUNC_COUNT*2 + 2, fields.length
|
|
93
|
+
assert_equal "not rtp or frame.number == 2 or frame.number == 3 or frame.number == 4 or frame.number == 5 or frame.number == 6 or frame.number == 9 or frame.number == 10 or frame.number == 11 or frame.number == 12 or frame.number == 13", filter
|
|
94
|
+
|
|
95
|
+
# Missing signaling (e.g. rtp not fully dissected) can be filled in.
|
|
96
|
+
packets, fields = gen_packets [
|
|
97
|
+
[[:udp, 1,2,3,4], {}],
|
|
98
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp", :"rtp.setup-frame" => "1"}],
|
|
99
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp"}],
|
|
100
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp"}],
|
|
101
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp"}],
|
|
102
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp"}],
|
|
103
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp"}], # skip
|
|
104
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp"}], # skip
|
|
105
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp"}], # skip
|
|
106
|
+
]
|
|
107
|
+
filter = Rtp.preprocess packets, fields
|
|
108
|
+
assert_equal TRUNC_COUNT + 1, packets.length
|
|
109
|
+
assert_equal TRUNC_COUNT + 1, fields.length
|
|
110
|
+
assert_equal "not rtp or frame.number == 2 or frame.number == 3 or frame.number == 4 or frame.number == 5 or frame.number == 6", filter
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
# We don't bother trying to fill in missing signaling for
|
|
114
|
+
# first packets in stream. Just skip it.
|
|
115
|
+
packets, fields = gen_packets [
|
|
116
|
+
[[:udp, 1,2,3,4], {}],
|
|
117
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp"}], #skip
|
|
118
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp"}], #skip
|
|
119
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp", :"rtp.setup-frame" => "1"}], # keep
|
|
120
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp"}], # keep
|
|
121
|
+
[[:udp, 3,4,5,6], {:rtp => "rtp"}], # keep
|
|
122
|
+
]
|
|
123
|
+
filter = Rtp.preprocess packets, fields
|
|
124
|
+
assert_equal 4, packets.length
|
|
125
|
+
assert_equal 4, fields.length
|
|
126
|
+
assert_equal "not rtp or frame.number == 4 or frame.number == 5 or frame.number == 6", filter
|
|
127
|
+
ensure
|
|
128
|
+
Rtp.const_set! :TRUNC_COUNT, trunc_count_save if trunc_count_save
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
Binary file
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# http://www.mudynamics.com
|
|
2
|
+
# http://labs.mudynamics.com
|
|
3
|
+
# http://www.pcapr.net
|
|
4
|
+
|
|
5
|
+
require 'mu/testcase'
|
|
6
|
+
require 'mu/scenario/pcap'
|
|
7
|
+
|
|
8
|
+
module Mu
|
|
9
|
+
class Scenario
|
|
10
|
+
module Pcap
|
|
11
|
+
|
|
12
|
+
class Test < Mu::TestCase
|
|
13
|
+
|
|
14
|
+
Packet = ::Struct.new(:payload, :skip)
|
|
15
|
+
class Packet
|
|
16
|
+
alias :skip? :skip
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
this_dir = File.dirname(File.expand_path(__FILE__))
|
|
20
|
+
PCAP_PATH = "#{this_dir}/sip_signalled_call_1.pcap"
|
|
21
|
+
File.exist?(PCAP_PATH) or raise "Test pcap not found #{PCAP_PATH}"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def test_validate_pcap_size
|
|
25
|
+
# Backup constants that this test alters.
|
|
26
|
+
max_size_save = Pcap::MAX_PCAP_SIZE
|
|
27
|
+
max_raw_size_save = Pcap::MAX_RAW_PCAP_SIZE
|
|
28
|
+
protos_save = Pcap::EXCLUDE_FROM_SIZE_CHECK
|
|
29
|
+
timeout_save = TSHARK_READ_TIMEOUT
|
|
30
|
+
|
|
31
|
+
# Smaller than max size.
|
|
32
|
+
size = Pcap.validate_pcap_size(PCAP_PATH)
|
|
33
|
+
assert_equal 4054, size
|
|
34
|
+
|
|
35
|
+
# Equal to max size.
|
|
36
|
+
begin
|
|
37
|
+
Pcap.const_set! :MAX_PCAP_SIZE, 4054
|
|
38
|
+
size = Pcap.validate_pcap_size(PCAP_PATH)
|
|
39
|
+
assert_equal 4054, size
|
|
40
|
+
ensure
|
|
41
|
+
Pcap.const_set! :MAX_PCAP_SIZE, max_size_save
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Bigger than max size.
|
|
45
|
+
begin
|
|
46
|
+
Pcap.const_set! :MAX_PCAP_SIZE, 4053
|
|
47
|
+
e = assert_raise PcapTooLarge do
|
|
48
|
+
Pcap.validate_pcap_size(PCAP_PATH)
|
|
49
|
+
end
|
|
50
|
+
assert e.message =~ /\b4054\b/, "Exception message should report actual size"
|
|
51
|
+
ensure
|
|
52
|
+
Pcap.const_set! :MAX_PCAP_SIZE, max_size_save
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Remove rtp from list of filtered protocols. We should report a bigger pcap now.
|
|
56
|
+
begin
|
|
57
|
+
Pcap.const_set! :EXCLUDE_FROM_SIZE_CHECK, []
|
|
58
|
+
size = Pcap.validate_pcap_size(PCAP_PATH)
|
|
59
|
+
assert_equal 4663, size
|
|
60
|
+
ensure
|
|
61
|
+
Pcap.const_set! :EXCLUDE_FROM_SIZE_CHECK, protos_save
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Add rtcp to list of filtered protocols. We should report a smaller pcap now.
|
|
65
|
+
begin
|
|
66
|
+
Pcap.const_set! :EXCLUDE_FROM_SIZE_CHECK, ['rtp', 'rtcp']
|
|
67
|
+
size = Pcap.validate_pcap_size(PCAP_PATH)
|
|
68
|
+
assert_equal 3548, size
|
|
69
|
+
ensure
|
|
70
|
+
Pcap.const_set! :EXCLUDE_FROM_SIZE_CHECK, protos_save
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Use actual file size in the event of a tshark timeout.
|
|
74
|
+
begin
|
|
75
|
+
Pcap.const_set! :TSHARK_READ_TIMEOUT, 0
|
|
76
|
+
size = Pcap.validate_pcap_size(PCAP_PATH)
|
|
77
|
+
assert_equal File.size(PCAP_PATH), size, "should have reported actual file size on timeout"
|
|
78
|
+
ensure
|
|
79
|
+
Pcap.const_set! :TSHARK_READ_TIMEOUT, timeout_save
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Use actual file size in the event of a tshark timeout.
|
|
83
|
+
begin
|
|
84
|
+
Pcap.const_set! :MAX_RAW_PCAP_SIZE, 1
|
|
85
|
+
e = assert_raise PcapTooLarge do
|
|
86
|
+
Pcap.validate_pcap_size(PCAP_PATH)
|
|
87
|
+
end
|
|
88
|
+
assert e.message =~ /\b4054\b/, "Exception message should report actual size"
|
|
89
|
+
ensure
|
|
90
|
+
Pcap.const_set! :MAX_RAW_PCAP_SIZE, max_raw_size_save
|
|
91
|
+
end
|
|
92
|
+
ensure
|
|
93
|
+
Pcap.const_set! :TSHARK_READ_TIMEOUT, timeout_save
|
|
94
|
+
Pcap.const_set! :MAX_PCAP_SIZE, max_size_save
|
|
95
|
+
Pcap.const_set! :MAX_RAW_PCAP_SIZE, max_raw_size_save
|
|
96
|
+
Pcap.const_set! :EXCLUDE_FROM_SIZE_CHECK, protos_save
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def test_export_to_archive
|
|
100
|
+
pcap_dir = File.expand_path(File.dirname(__FILE__) + "/test_data")
|
|
101
|
+
Dir.glob("#{pcap_dir}/*.pcap") do |pcap|
|
|
102
|
+
Dir.mktmpdir do |tmp|
|
|
103
|
+
Dir.chdir(tmp) do
|
|
104
|
+
io = Pcap.export_to_par pcap
|
|
105
|
+
open("export.par", 'wb') do |f|
|
|
106
|
+
while chunk = io.read(4096)
|
|
107
|
+
f.write chunk
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
# Archive file can be extracted.
|
|
111
|
+
unzipped = system('unzip export.par > out 2>&1')
|
|
112
|
+
assert unzipped, "failed to extract par file:\n" + File.read('out')
|
|
113
|
+
|
|
114
|
+
# Normalized pcap is well formed.
|
|
115
|
+
well_formed_pcap = system('tshark -r normalized.pcap > out 2>&1')
|
|
116
|
+
assert well_formed_pcap, "Tshark did not like this pcap. Is it malformed? \n" + File.read('out')
|
|
117
|
+
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
RE_MU_RUBY_VER = /1\.8\.6/
|
|
125
|
+
def get_pcap2scenario_ruby
|
|
126
|
+
ENV['PATH'].split(":").each do |dir|
|
|
127
|
+
dir = File.expand_path dir
|
|
128
|
+
ruby = dir + '/ruby'
|
|
129
|
+
if File.file? ruby and File.executable? ruby
|
|
130
|
+
ver = `#{ruby} -v`
|
|
131
|
+
if ver =~ RE_MU_RUBY_VER
|
|
132
|
+
return ruby
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
nil
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def test_archive_to_scenario
|
|
141
|
+
mu_root = ENV['MU_ROOT']
|
|
142
|
+
if not mu_root
|
|
143
|
+
warn "Skipping pcap2scenario tests because MU_ROOT is not available"
|
|
144
|
+
return
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
path_save = ENV['PATH']
|
|
148
|
+
ruby = get_pcap2scenario_ruby
|
|
149
|
+
assert ruby, "Could not find ruby executable that matches #{RE_MU_RUBY_VER}"
|
|
150
|
+
|
|
151
|
+
pcap_dir = File.expand_path(File.dirname(__FILE__) + "/test_data")
|
|
152
|
+
msl_dir = File.expand_path("#{mu_root}/test/mu/scenario/from_pcap")
|
|
153
|
+
Dir.glob("#{pcap_dir}/*.pcap") do |pcap|
|
|
154
|
+
expected_msl = File.basename(pcap, '.pcap') + '.msl'
|
|
155
|
+
expected_msl = File.join(msl_dir, expected_msl)
|
|
156
|
+
begin
|
|
157
|
+
Dir.mktmpdir do |tmp|
|
|
158
|
+
Dir.chdir(tmp) do
|
|
159
|
+
# Get par file
|
|
160
|
+
io = Pcap.export_to_par pcap, :isolate_l7 => true
|
|
161
|
+
open("export.par", 'wb') do |f|
|
|
162
|
+
while chunk = io.read(4096)
|
|
163
|
+
f.write chunk
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Create scenario from par file.
|
|
168
|
+
created_scenario = system("#{ruby} #{mu_root}/tools/scenarios/pcap2scenario.rb -wmi export.par > scenario.msl 2> err")
|
|
169
|
+
assert created_scenario, "Pcap2scenario failed with:\n" + File.read('err')
|
|
170
|
+
|
|
171
|
+
# And make sure result is the same as what you get when starting from pcap.
|
|
172
|
+
assert_files_same expected_msl, "scenario.msl"
|
|
173
|
+
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
rescue Exception => e
|
|
177
|
+
e.backtrace << "First pcap to failed was #{pcap}. Skipping subsequent pcaps."
|
|
178
|
+
raise e
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
end
|