pcapr-local 0.1.10
Sign up to get free protection for your applications and to get access to all the features.
- 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,76 @@
|
|
1
|
+
# http://www.mudynamics.com
|
2
|
+
# http://labs.mudynamics.com
|
3
|
+
# http://www.pcapr.net
|
4
|
+
|
5
|
+
require 'mu/testcase'
|
6
|
+
require 'mu/pcap/reader'
|
7
|
+
|
8
|
+
module Mu
|
9
|
+
class Pcap
|
10
|
+
class Reader
|
11
|
+
|
12
|
+
class Test < Mu::TestCase
|
13
|
+
class MyReader < Reader
|
14
|
+
FAMILY_TO_READER[:my_reader] = self
|
15
|
+
|
16
|
+
def do_read_message! bytes, state
|
17
|
+
state[:bytes_recv] ||= 0
|
18
|
+
if bytes.size >= 10
|
19
|
+
state[:bytes_recv] += 10
|
20
|
+
bytes.slice!(0,10)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def do_record_write bytes, state
|
25
|
+
state[:bytes_sent] ||= 0
|
26
|
+
state[:bytes_sent] += bytes.size
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_basics
|
31
|
+
# initialize
|
32
|
+
reader = MyReader.new
|
33
|
+
|
34
|
+
# read_message/record_write
|
35
|
+
bytes = "a" * 11
|
36
|
+
state = {}
|
37
|
+
assert_equal "a"*10, reader.read_message(bytes, state)
|
38
|
+
assert_equal "a"*11, bytes
|
39
|
+
assert_equal "a"*10, reader.read_message!(bytes, state)
|
40
|
+
assert_equal "a", bytes
|
41
|
+
assert_equal 20, state[:bytes_recv]
|
42
|
+
assert_nil reader.read_message('a', state)
|
43
|
+
reader.record_write "foo", state
|
44
|
+
assert_equal 3, state[:bytes_sent]
|
45
|
+
reader.record_write "foo", state
|
46
|
+
assert_equal 6, state[:bytes_sent]
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_family
|
50
|
+
reader = Reader.reader(:my_reader)
|
51
|
+
assert_kind_of MyReader, reader
|
52
|
+
assert_nil Reader.reader(:none)
|
53
|
+
assert_raises(ArgumentError) { Reader.reader(:lkjlkjkl) }
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_exception
|
57
|
+
reader = MyReader.new
|
58
|
+
state = {}
|
59
|
+
def reader.do_read_message! bytes, state
|
60
|
+
raise "Yikes!"
|
61
|
+
end
|
62
|
+
def reader.do_record_write bytes, state
|
63
|
+
raise "Huh?"
|
64
|
+
end
|
65
|
+
|
66
|
+
reader.pcap2scenario = true
|
67
|
+
# Return nil instead of raising an exception during pcap2scenario
|
68
|
+
assert_nil reader.read_message('a'*10, state)
|
69
|
+
assert_nil reader.record_write('a'*10, state)
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,426 @@
|
|
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 TCP
|
11
|
+
|
12
|
+
class Test < Mu::TestCase
|
13
|
+
def test_basics
|
14
|
+
tcp = TCP.new
|
15
|
+
tcp.src_port = 0x3039
|
16
|
+
tcp.dst_port = 0x0050
|
17
|
+
tcp.flags = 2
|
18
|
+
tcp.seq = 0
|
19
|
+
tcp.ack = 0
|
20
|
+
tcp.window = 0x3de0
|
21
|
+
tcp.urgent = 0
|
22
|
+
tcp.payload = 'hello'
|
23
|
+
tcp.payload_raw = 'hello'
|
24
|
+
|
25
|
+
bytes =
|
26
|
+
"\x30\x39" + # src port
|
27
|
+
"\x00\x50" + # dst port
|
28
|
+
"\x00\x00\x00\x00" + # seq
|
29
|
+
"\x00\x00\x00\x00" + # dst
|
30
|
+
"\x50" + # offset
|
31
|
+
"\x02" + # flags
|
32
|
+
"\x3d\xe0" + # window
|
33
|
+
"\x00\x00" + # checksum
|
34
|
+
"\x00\x00" + # urp
|
35
|
+
'hello'
|
36
|
+
tcp_in = TCP.from_bytes bytes
|
37
|
+
assert_equal tcp_in, tcp
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_reorder
|
41
|
+
# empty stream
|
42
|
+
assert_equal [], TCP.reorder([])
|
43
|
+
|
44
|
+
# one flow
|
45
|
+
tcp = tcp(:client, 'hello')
|
46
|
+
assert_equal [tcp], TCP.reorder([tcp])
|
47
|
+
|
48
|
+
# different flows
|
49
|
+
tcp1 = tcp(:client, 'hello')
|
50
|
+
tcp2 = tcp(:server, 'hello')
|
51
|
+
assert_equal [tcp1, tcp2], TCP.reorder([tcp1, tcp2])
|
52
|
+
|
53
|
+
# hello, world
|
54
|
+
tcp1 = tcp(:client, 'hello')
|
55
|
+
tcp2 = tcp(:client, 'world', 5)
|
56
|
+
assert_equal [tcp1, tcp2], TCP.reorder([tcp1, tcp2])
|
57
|
+
|
58
|
+
# world, discard old hello
|
59
|
+
tcp1 = tcp(:client, 'world', 5)
|
60
|
+
tcp2 = tcp(:client, 'hello')
|
61
|
+
assert_equal [tcp1], TCP.reorder([tcp1, tcp2])
|
62
|
+
|
63
|
+
# discard duplicate
|
64
|
+
tcp1 = tcp(:client, 'hello')
|
65
|
+
tcp2 = tcp(:client, 'hello')
|
66
|
+
assert_equal [tcp1], TCP.reorder([tcp1, tcp2])
|
67
|
+
|
68
|
+
# overlap
|
69
|
+
tcp1 = tcp(:client, 'hello')
|
70
|
+
tcp2 = tcp(:client, 'oworld', 4)
|
71
|
+
TCP.reorder [tcp1, tcp2]
|
72
|
+
|
73
|
+
# out of order packets
|
74
|
+
tcp1 = tcp(:client, 'hello')
|
75
|
+
tcp2 = tcp(:client, 'ld', 8)
|
76
|
+
tcp3 = tcp(:client, 'wor', 5)
|
77
|
+
assert_equal [tcp1, tcp3, tcp2], TCP.reorder([tcp1, tcp2, tcp3])
|
78
|
+
|
79
|
+
# out of order packets
|
80
|
+
tcp1 = tcp(:client, 'hello')
|
81
|
+
tcp2 = tcp(:client, 'wor', 5)
|
82
|
+
tcp3 = tcp(:client, 'l', 8)
|
83
|
+
tcp4 = tcp(:client, 'd', 9)
|
84
|
+
[[tcp2, tcp3, tcp4],
|
85
|
+
[tcp2, tcp4, tcp3],
|
86
|
+
[tcp3, tcp2, tcp4],
|
87
|
+
[tcp3, tcp4, tcp2],
|
88
|
+
[tcp4, tcp2, tcp3],
|
89
|
+
[tcp4, tcp3, tcp2]].each do |tcps|
|
90
|
+
assert_equal [tcp1, tcp2, tcp3, tcp4],
|
91
|
+
TCP.reorder([tcp1, *tcps])
|
92
|
+
end
|
93
|
+
|
94
|
+
# unfilled gap
|
95
|
+
tcp1 = tcp(:client, 'hello')
|
96
|
+
tcp2 = tcp(:client, 'world', 6)
|
97
|
+
assert_raises ReorderError do
|
98
|
+
TCP.reorder [tcp1, tcp2]
|
99
|
+
end
|
100
|
+
|
101
|
+
# syn
|
102
|
+
tcp1 = tcp(:client, '', 0, TCP::TH_SYN)
|
103
|
+
tcp2 = tcp(:client, 'hello', 1)
|
104
|
+
assert_equal [tcp1, tcp2], TCP.reorder([tcp1, tcp2])
|
105
|
+
|
106
|
+
# wrap sequence number
|
107
|
+
tcp1 = tcp(:client, 'hello', 2**32 - 1)
|
108
|
+
tcp2 = tcp(:client, 'world', 4)
|
109
|
+
assert_equal [tcp1, tcp2], TCP.reorder([tcp1, tcp2])
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_merge
|
113
|
+
assert_equal [], TCP.merge([])
|
114
|
+
|
115
|
+
# Ethernet
|
116
|
+
ethernet = Ethernet.new
|
117
|
+
assert_equal [ethernet], TCP.merge([ethernet])
|
118
|
+
|
119
|
+
# IPv4
|
120
|
+
ipv4 = IPv4.new
|
121
|
+
ipv4.src = '10.0.0.1'
|
122
|
+
ipv4.dst = '10.0.0.2'
|
123
|
+
ipv4.proto = IPv4::IPPROTO_TCP
|
124
|
+
ethernet = Ethernet.new
|
125
|
+
ethernet.type = Ethernet::ETHERTYPE_IP
|
126
|
+
ethernet.payload = ipv4
|
127
|
+
assert_equal [ethernet], TCP.merge([ethernet])
|
128
|
+
|
129
|
+
# TCP, no data
|
130
|
+
tcp = tcp(:client, '')
|
131
|
+
assert_equal [], TCP.merge([tcp])
|
132
|
+
|
133
|
+
# TCP
|
134
|
+
tcp = tcp(:client, 'hello')
|
135
|
+
assert_equal [tcp], TCP.merge([tcp])
|
136
|
+
|
137
|
+
# Two TCP in different directions
|
138
|
+
tcp1 = tcp(:client, 'hello')
|
139
|
+
tcp2 = tcp(:server, 'world')
|
140
|
+
assert_equal [tcp1, tcp2], TCP.merge([tcp1, tcp2])
|
141
|
+
|
142
|
+
# Basic merge (original payloads not modified)
|
143
|
+
tcp1 = tcp(:client, 'hello')
|
144
|
+
tcp2 = tcp(:client, 'world', 5)
|
145
|
+
tcp3 = tcp(:client, 'three', 10)
|
146
|
+
tcp = tcp(:client, 'helloworldthree')
|
147
|
+
assert_equal [tcp], TCP.merge([tcp1, tcp2, tcp3])
|
148
|
+
assert_equal 'hello', tcp1.payload.payload.payload
|
149
|
+
assert_equal 'world', tcp2.payload.payload.payload
|
150
|
+
|
151
|
+
# overlap - favor second packet
|
152
|
+
tcp1 = tcp(:client, 'hello')
|
153
|
+
tcp2 = tcp(:client, 'Xworld', 4)
|
154
|
+
tcp3 = tcp(:client, 'three', 10)
|
155
|
+
tcp = tcp(:client, 'helloworldthree')
|
156
|
+
assert_equal [tcp], TCP.merge([tcp1, tcp2, tcp3])
|
157
|
+
|
158
|
+
# gap - raise error
|
159
|
+
tcp1 = tcp(:client, 'hello')
|
160
|
+
tcp2 = tcp(:client, 'world', 6)
|
161
|
+
assert_raises MergeError do
|
162
|
+
TCP.merge([tcp1, tcp2])
|
163
|
+
end
|
164
|
+
|
165
|
+
# sequence number wrap
|
166
|
+
tcp1 = tcp(:client, 'hello', 2**32 - 1)
|
167
|
+
tcp2 = tcp(:client, 'world', 4)
|
168
|
+
tcp = tcp(:client, 'helloworld', 2**32 - 1)
|
169
|
+
assert_equal [tcp], TCP.merge([tcp1, tcp2])
|
170
|
+
|
171
|
+
# sequence number wrap with overlap
|
172
|
+
tcp1 = tcp(:client, 'hello', 2**32 - 1)
|
173
|
+
tcp2 = tcp(:client, 'Xworld', 3)
|
174
|
+
tcp = tcp(:client, 'helloworld', 2**32 - 1)
|
175
|
+
assert_equal [tcp], TCP.merge([tcp1, tcp2])
|
176
|
+
end
|
177
|
+
|
178
|
+
def http_wrap bytes
|
179
|
+
"GET / HTTP/1.1\r\n" +
|
180
|
+
"some-header: foo\r\n" +
|
181
|
+
"some-length: 34\r\n" +
|
182
|
+
"Content-Length: #{bytes.length}\r\n" +
|
183
|
+
"Content-Something: baz\r\n" +
|
184
|
+
"\r\n" +
|
185
|
+
bytes
|
186
|
+
end
|
187
|
+
|
188
|
+
def make_stream bytes, direction, connection=1, offset=0, seg_size=1
|
189
|
+
io = StringIO.new bytes
|
190
|
+
packets = []
|
191
|
+
while bytes = io.read(seg_size)
|
192
|
+
packets << tcp(direction, bytes, offset, 0, connection)
|
193
|
+
offset += bytes.length
|
194
|
+
end
|
195
|
+
packets
|
196
|
+
end
|
197
|
+
|
198
|
+
TCP_FLAGS = 0
|
199
|
+
def test_message_assembly
|
200
|
+
message_1 = http_wrap("0123456789" * 100).freeze
|
201
|
+
message_2 = http_wrap("abcdefghij" * 100).freeze
|
202
|
+
message_3 = http_wrap("ABCDEFGHIJ" * 100).freeze
|
203
|
+
|
204
|
+
# Reassemble segments into message
|
205
|
+
packets = make_stream message_1, :client, 1
|
206
|
+
assert_equal [tcp(:client, message_1)], TCP.merge(packets)
|
207
|
+
|
208
|
+
# Insert server packet in front (should have no effect)
|
209
|
+
packets = make_stream message_1, :client, 1
|
210
|
+
server_packet = tcp(:server, "bytes")
|
211
|
+
packets.unshift server_packet
|
212
|
+
expect = [
|
213
|
+
server_packet,
|
214
|
+
tcp(:client, message_1, 0, TCP_FLAGS, 1)
|
215
|
+
]
|
216
|
+
assert_equal expect, TCP.merge(packets)
|
217
|
+
|
218
|
+
# One interleaved packet from a different connection.
|
219
|
+
# HTTP message should be reassembled and appear second.
|
220
|
+
packets = make_stream message_1, :client, 1
|
221
|
+
extra_packet = tcp(:server, "X"*40, 0, TCP_FLAGS, 3)
|
222
|
+
packets[packets.length/2, 0] = [extra_packet]
|
223
|
+
expect = [
|
224
|
+
extra_packet,
|
225
|
+
tcp(:client, message_1, 0, TCP_FLAGS, 1)
|
226
|
+
]
|
227
|
+
assert_equal expect, TCP.merge(packets)
|
228
|
+
|
229
|
+
# Two messages in a row with one interleaved packet
|
230
|
+
# from a different connection in middle of first message
|
231
|
+
#
|
232
|
+
# The first message should be ressambled after the extra packet.
|
233
|
+
packets = make_stream message_1 + message_2, :client, 1
|
234
|
+
extra_packet = tcp(:server, "XXXXXX", 0, TCP_FLAGS, 3)
|
235
|
+
packets[packets.length/4, 0] = [extra_packet]
|
236
|
+
expect = [
|
237
|
+
extra_packet,
|
238
|
+
tcp(:client, message_1, 0, TCP_FLAGS, 1),
|
239
|
+
tcp(:client, message_2, message_1.length, TCP_FLAGS, 1),
|
240
|
+
]
|
241
|
+
assert_equal expect, TCP.merge(packets) # wrong?
|
242
|
+
|
243
|
+
# Two messages in a row with one interleaved packet
|
244
|
+
# from a different connection in middle of second message
|
245
|
+
# The second message should be reassembled after the
|
246
|
+
# extra packet.
|
247
|
+
packets = make_stream message_1 + message_2, :client, 1
|
248
|
+
extra_packet = tcp(:server, "bytes", 0, TCP_FLAGS, 3)
|
249
|
+
packets[(packets.length*0.75).to_i, 0] = [extra_packet]
|
250
|
+
expect = [
|
251
|
+
tcp(:client, message_1, 0, TCP_FLAGS, 1),
|
252
|
+
extra_packet,
|
253
|
+
tcp(:client, message_2, message_1.length, TCP_FLAGS, 1),
|
254
|
+
]
|
255
|
+
assert_equal expect, TCP.merge(packets)
|
256
|
+
|
257
|
+
# Http message, followed by non http message with interleaved
|
258
|
+
# packet. Packets should not be merged or split because one
|
259
|
+
# of the flows has an incomplete message.
|
260
|
+
part1 = message_1
|
261
|
+
part2 = "X"*50
|
262
|
+
part3 = "Z"*50
|
263
|
+
message_bytes = part1 + part2 + part3
|
264
|
+
packets = make_stream message_bytes, :client, 1
|
265
|
+
extra_packet = tcp(:server, "EXTRA", 0, TCP_FLAGS, 3)
|
266
|
+
packets[-50, 0] = [extra_packet]
|
267
|
+
seq = 0
|
268
|
+
expect = [
|
269
|
+
tcp(:client, part1+part2, seq, TCP_FLAGS, 1),
|
270
|
+
extra_packet,
|
271
|
+
tcp(:client, part3, (part1.size + part2.size), TCP_FLAGS, 1),
|
272
|
+
]
|
273
|
+
assert_equal expect, TCP.merge(packets)
|
274
|
+
|
275
|
+
# 3 Messages with interleaved packets from a different connection
|
276
|
+
# in the middle of the 2nd message and between the 2nd and 3rd
|
277
|
+
# messages.
|
278
|
+
packets = make_stream message_1 + message_2, :client, 1
|
279
|
+
extra_packet_1 = tcp(:client, "request", 0, TCP_FLAGS, 3)
|
280
|
+
packets[-packets.length/4, 0] = [extra_packet_1]
|
281
|
+
extra_packet_2 = tcp(:client, "request2", 0, TCP_FLAGS, 4)
|
282
|
+
packets << extra_packet_2
|
283
|
+
packets.concat make_stream(message_3, :client, 1, (message_1 + message_2).size)
|
284
|
+
seq = 0
|
285
|
+
expect = [
|
286
|
+
tcp(:client, message_1, seq, TCP_FLAGS, 1),
|
287
|
+
extra_packet_1,
|
288
|
+
tcp(:client, message_2, seq+=message_1.size, TCP_FLAGS, 1),
|
289
|
+
extra_packet_2,
|
290
|
+
tcp(:client, message_3, seq+=message_2.size, TCP_FLAGS, 1),
|
291
|
+
]
|
292
|
+
assert_equal expect, TCP.merge(packets)
|
293
|
+
|
294
|
+
# One interleaved packet from server side of same connection,
|
295
|
+
# message should be reassembled.
|
296
|
+
packets = make_stream message_1, :client, 1
|
297
|
+
part1 = TCP.merge(packets[0...packets.length/2])
|
298
|
+
part2 = TCP.merge(packets[packets.length/2..-1])
|
299
|
+
extra_packet = tcp(:server, message_2, 0, TCP_FLAGS, 1)
|
300
|
+
packets = [part1, extra_packet, part2].flatten
|
301
|
+
expect = [
|
302
|
+
extra_packet,
|
303
|
+
tcp(:client, message_1, 0, TCP_FLAGS, 1),
|
304
|
+
]
|
305
|
+
assert_equal expect, TCP.merge(packets)
|
306
|
+
|
307
|
+
# Alternate packets from different connections, messages should be assembled.
|
308
|
+
stream_1 = make_stream message_1, :client, 1
|
309
|
+
stream_2 = make_stream message_2, :server, 2
|
310
|
+
packets = stream_1.zip(stream_2).flatten
|
311
|
+
expect = [
|
312
|
+
tcp(:client, message_1, 0, TCP_FLAGS, 1),
|
313
|
+
tcp(:server, message_2, 0, TCP_FLAGS, 2)
|
314
|
+
]
|
315
|
+
assert_equal expect, TCP.merge(packets)
|
316
|
+
|
317
|
+
# Switch first packet
|
318
|
+
stream_1 = make_stream message_1, :client, 1
|
319
|
+
stream_2 = make_stream message_2, :server, 2
|
320
|
+
packets = stream_2.zip(stream_1).flatten
|
321
|
+
expect = [
|
322
|
+
tcp(:server, message_2, 0, TCP_FLAGS, 2),
|
323
|
+
tcp(:client, message_1, 0, TCP_FLAGS, 1)
|
324
|
+
]
|
325
|
+
assert_equal expect, TCP.merge(packets)
|
326
|
+
|
327
|
+
# Alternate packets from different sides of same connection,
|
328
|
+
# messages should be reassmbled.
|
329
|
+
stream_1 = make_stream message_1, :client, 1
|
330
|
+
stream_2 = make_stream message_2, :server, 1
|
331
|
+
packets = stream_1.zip(stream_2).flatten
|
332
|
+
stream_1 = make_stream message_1, :client, 1
|
333
|
+
stream_2 = make_stream message_2, :server, 1
|
334
|
+
expect = [
|
335
|
+
tcp(:client, message_1, 0, TCP_FLAGS, 1),
|
336
|
+
tcp(:server, message_2, 0, TCP_FLAGS, 1),
|
337
|
+
]
|
338
|
+
assert_equal expect, TCP.merge(packets)
|
339
|
+
|
340
|
+
# Messages should not be merged because they
|
341
|
+
# are too big and would need to be split into
|
342
|
+
# 64K chunks.
|
343
|
+
part_2 = http_wrap("Z" * 80 * 1024)
|
344
|
+
part_1 = part_2.slice!(0,70*1024)
|
345
|
+
packets = [
|
346
|
+
tcp(:client, part_1, 0, TCP_FLAGS),
|
347
|
+
tcp(:server, message_2, 0, TCP_FLAGS),
|
348
|
+
tcp(:client, part_2, 0, TCP_FLAGS),
|
349
|
+
]
|
350
|
+
expect = [
|
351
|
+
tcp(:client, part_1, 0, TCP_FLAGS),
|
352
|
+
tcp(:server, message_2, 0, TCP_FLAGS),
|
353
|
+
tcp(:client, part_2, 0, TCP_FLAGS),
|
354
|
+
]
|
355
|
+
assert_equal expect, TCP.merge(packets)
|
356
|
+
end
|
357
|
+
|
358
|
+
def test_split
|
359
|
+
assert_equal [], TCP.split([])
|
360
|
+
|
361
|
+
tcp = tcp(:client, 'A' * (65535 - 54))
|
362
|
+
assert_equal [tcp], TCP.split([tcp])
|
363
|
+
|
364
|
+
tcp = tcp(:client, 'A' * 65535)
|
365
|
+
tcp1 = tcp(:client, 'A' * (65535 - 54))
|
366
|
+
tcp2 = tcp(:client, 'A' * 54, (65535 - 54))
|
367
|
+
assert_equal [tcp1, tcp2], TCP.split([tcp])
|
368
|
+
end
|
369
|
+
|
370
|
+
def test_tcp_seq_sub
|
371
|
+
assert_equal 1, TCP.seq_sub(2, 1)
|
372
|
+
assert_equal 0, TCP.seq_sub(1, 1)
|
373
|
+
assert_equal 1, TCP.seq_sub(0, 2**32-1)
|
374
|
+
assert_equal(-1, TCP.seq_sub(2**32-1, 0))
|
375
|
+
assert_equal 0, TCP.seq_sub(2**32-1, 2**32-1)
|
376
|
+
|
377
|
+
assert TCP.seq_eq(0, 0)
|
378
|
+
assert TCP.seq_eq(2**32, 0)
|
379
|
+
assert TCP.seq_eq(0, 2**32)
|
380
|
+
|
381
|
+
assert TCP.seq_lt(1, 2)
|
382
|
+
assert !TCP.seq_lt(2, 1)
|
383
|
+
assert !TCP.seq_lt(2, 2)
|
384
|
+
assert TCP.seq_lt(2**32-1, 0)
|
385
|
+
assert !TCP.seq_lt(0, 2**32-1)
|
386
|
+
|
387
|
+
assert TCP.seq_lte(1, 2)
|
388
|
+
assert !TCP.seq_lte(2, 1)
|
389
|
+
assert TCP.seq_lte(2, 2)
|
390
|
+
assert TCP.seq_lt(2**32-1, 0)
|
391
|
+
assert !TCP.seq_lt(0, 2**32-1)
|
392
|
+
end
|
393
|
+
|
394
|
+
def tcp sender, payload, seq=0, flags=0, connection=1
|
395
|
+
tcp = TCP.new
|
396
|
+
ipv4 = IPv4.new
|
397
|
+
ethernet = Ethernet.new
|
398
|
+
if sender == :client
|
399
|
+
ethernet.src = '00:01:00:00:00:01'
|
400
|
+
ethernet.dst = '00:01:00:00:00:02'
|
401
|
+
ipv4.src = '10.0.0.1'
|
402
|
+
ipv4.dst = '10.0.0.2'
|
403
|
+
tcp.src_port = connection
|
404
|
+
tcp.dst_port = connection + 10000
|
405
|
+
else
|
406
|
+
ethernet.src = '00:01:00:00:00:02'
|
407
|
+
ethernet.dst = '00:01:00:00:00:01'
|
408
|
+
ipv4.src = '10.0.0.2'
|
409
|
+
ipv4.dst = '10.0.0.1'
|
410
|
+
tcp.src_port = connection + 10000
|
411
|
+
tcp.dst_port = connection
|
412
|
+
end
|
413
|
+
tcp.flags = flags
|
414
|
+
tcp.seq = seq
|
415
|
+
tcp.payload = payload
|
416
|
+
ipv4.proto = IPv4::IPPROTO_TCP
|
417
|
+
ipv4.payload = tcp
|
418
|
+
ethernet.type = Ethernet::ETHERTYPE_IP
|
419
|
+
ethernet.payload = ipv4
|
420
|
+
return ethernet
|
421
|
+
end
|
422
|
+
end
|
423
|
+
|
424
|
+
end
|
425
|
+
end
|
426
|
+
end
|