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
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/test/mu/tc_pcap.rb
ADDED
@@ -0,0 +1,39 @@
|
|
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
|
+
|
11
|
+
class Test < Mu::TestCase
|
12
|
+
def test_basics
|
13
|
+
pcap = Pcap.new
|
14
|
+
pkthdr = Pkthdr.new
|
15
|
+
pkthdr.caplen = pkthdr.len = 77
|
16
|
+
ethernet = Ethernet.new
|
17
|
+
ethernet.src = '00:01:01:00:00:01'
|
18
|
+
ethernet.dst = '00:01:01:00:00:02'
|
19
|
+
ethernet.type = Ethernet::ETHERTYPE_IP
|
20
|
+
ethernet.payload = ethernet.payload_raw = 'X' * 73
|
21
|
+
pkthdr.pkt = ethernet
|
22
|
+
pcap.pkthdrs << pkthdr
|
23
|
+
|
24
|
+
bytes = "\xa1\xb2\xc3\xd4" + "\x00\x02" + "\x00\x04" +
|
25
|
+
"\x00\x00\x00\x00" + "\x00\x00\x00\x00" +
|
26
|
+
"\x00\x00\x05\xdc" + "\x00\x00\x00\x00" +
|
27
|
+
"\x00\x00\x00\x00" + "\x00\x00\x00\x00" + # pkthdr
|
28
|
+
"\x00\x00\x00\x4d" + "\x00\x00\x00\x4d" +
|
29
|
+
"\x00\x00\x00\x02" + ("X" * 73)
|
30
|
+
pcap_in = nil
|
31
|
+
with_no_stderr do # supress warning about malformed IPv4
|
32
|
+
pcap_in = Pcap.read StringIO.new(bytes)
|
33
|
+
end
|
34
|
+
assert_equal pcap_in, pcap
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
data/test/mu/testcase.rb
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
# http://www.mudynamics.com
|
2
|
+
# http://labs.mudynamics.com
|
3
|
+
# http://www.pcapr.net
|
4
|
+
|
5
|
+
require 'tempfile'
|
6
|
+
require 'test/unit'
|
7
|
+
require 'pp' # Require to make pp available in tests
|
8
|
+
|
9
|
+
|
10
|
+
module Mu
|
11
|
+
class TestCase < ::Test::Unit::TestCase
|
12
|
+
def setup
|
13
|
+
self.reset
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.reset
|
17
|
+
# Reset random number generator and Time.now to known values
|
18
|
+
srand 31337
|
19
|
+
end
|
20
|
+
|
21
|
+
def reset
|
22
|
+
self.class.reset
|
23
|
+
end
|
24
|
+
|
25
|
+
def assert_files_same expected_file, actual_file, message=nil
|
26
|
+
expected_file = File.expand_path expected_file
|
27
|
+
actual_file = File.expand_path actual_file
|
28
|
+
|
29
|
+
# Set TC_CREATE env variable to create missing stdout files
|
30
|
+
create_missing_file = ENV['TC_CREATE'].to_s.length > 0
|
31
|
+
# Set TC_UPDATE env variable to update stdout files instead of failing (be careful!)
|
32
|
+
bulk_update = ENV['TC_UPDATE'].to_s.length > 0
|
33
|
+
|
34
|
+
if create_missing_file and not File.exists? expected_file
|
35
|
+
File.open("/dev/tty", 'w') do |tty|
|
36
|
+
tty.puts "Warning: copying #{actual_file} to #{expected_file}"
|
37
|
+
end
|
38
|
+
File.open(expected_file, 'w') {|f| f.write File.read(actual_file)}
|
39
|
+
end
|
40
|
+
|
41
|
+
assert File.exists?(expected_file), "File #{expected_file.inspect} does not exist"
|
42
|
+
assert File.exists?(actual_file), "File #{actual_file.inspect} does not exist"
|
43
|
+
|
44
|
+
message ||= "Files differ: #{expected_file} #{actual_file}"
|
45
|
+
assert_block message do
|
46
|
+
$stderr.puts `diff -ub #{expected_file} #{actual_file} 2>&1`
|
47
|
+
if $?.exitstatus == 0
|
48
|
+
return true
|
49
|
+
end
|
50
|
+
|
51
|
+
# Hook for graphical diff/merge tools
|
52
|
+
if diff = ENV['DIFF']
|
53
|
+
puts `#{diff} #{expected_file} #{actual_file}`
|
54
|
+
else
|
55
|
+
$stderr.puts "You may want to rerun test with DIFF env variable set to a graphical diff/merge tool"
|
56
|
+
end
|
57
|
+
|
58
|
+
if bulk_update
|
59
|
+
File.open("/dev/tty", 'w') do |tty|
|
60
|
+
tty.puts "Warning: updating expected output at #{actual_file} to #{expected_file}"
|
61
|
+
end
|
62
|
+
File.open(expected_file, 'w') {|f| f.write File.read(actual_file)}
|
63
|
+
next true
|
64
|
+
end
|
65
|
+
|
66
|
+
false
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Suppress output to stderr. For testing code that may log to stderr.
|
71
|
+
def with_no_stderr # block
|
72
|
+
begin
|
73
|
+
old_stderr = $stderr
|
74
|
+
$stderr = StringIO.new
|
75
|
+
yield
|
76
|
+
ensure
|
77
|
+
$stderr = old_stderr
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def default_test
|
82
|
+
# Defining this method prevents this class from running and failing
|
83
|
+
# due to lack of tests.
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
Binary file
|
@@ -0,0 +1,3 @@
|
|
1
|
+
{"status":"indexed","updated_at":"2010/12/22 01:30:20 +0000","_id":"6808db6ca2264c01780e7fb4fb5ca623","_rev":"3-a5530512f0c1010c7d82c7f1dda0d516","type":"pcap","index":{"about":{"packets":28,"hosts":10,"version":"4.5.41604","services":7,"flows":5,"duration":9.45506},"services":["browser","nbns","arp","sip","sip/sdp","rtp","icmp"]},"filename":"A1.pcap","stat":{"inode":6395143,"size":9300,"ctime":"2010/12/18 01:41:41 +0000"},"created_at":"2010/12/22 01:30:18 +0000"}
|
2
|
+
{"status":"indexed","updated_at":"2010/12/22 01:30:23 +0000","_id":"6808db6ca2264c01780e7fb4fb5c9022","_rev":"3-1121a5eff55ba3d3c0b6e6177c5dcfcf","type":"pcap","index":{"about":{"packets":2,"hosts":3,"version":"4.5.41604","services":1,"flows":0,"duration":4.59072e-05},"services":["arp"]},"filename":"arp.pcap","stat":{"inode":6395176,"size":140,"ctime":"2010/12/20 18:56:49 +0000"},"created_at":"2010/12/22 01:30:18 +0000"}
|
3
|
+
{"status":"indexed","updated_at":"2010/12/22 01:30:26 +0000","_id":"6808db6ca2264c01780e7fb4fb5c9ada","_rev":"3-8c43c559332f027de3b27ce59c54a41b","type":"pcap","index":{"about":{"packets":22,"hosts":5,"version":"4.5.41604","services":6,"flows":4,"duration":6.29398},"services":["arp","sip/sdp","sip","rtcp","rtp","icmp"]},"filename":"sip_signalled_call_1.pcap","stat":{"inode":6395187,"size":5039,"ctime":"2010/12/21 02:04:04 +0000"},"created_at":"2010/12/22 01:30:18 +0000"}
|
Binary file
|
@@ -0,0 +1,181 @@
|
|
1
|
+
# http://www.mudynamics.com
|
2
|
+
# http://labs.mudynamics.com
|
3
|
+
# http://www.pcapr.net
|
4
|
+
|
5
|
+
$: << File.expand_path(File.dirname(__FILE__) + '../../../../lib')
|
6
|
+
|
7
|
+
require 'pcapr_local'
|
8
|
+
require 'test/unit'
|
9
|
+
|
10
|
+
module CouchTest
|
11
|
+
def datafile
|
12
|
+
nil
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns user config but with parameters to changed to prevent clobbering user data.
|
16
|
+
def config
|
17
|
+
config = PcaprLocal::Config.config
|
18
|
+
config['couch']['database'] = "#{config['couch']['database']}_test"
|
19
|
+
config['install_dir'] = "/tmp/pcapr_local_test"
|
20
|
+
config['pcap_dir'] = "/tmp/pcapr_local_test/pcaps"
|
21
|
+
config['index_dir'] = "/tmp/pcapr_local_test/indexes"
|
22
|
+
config['app']['port'] = config['app']['port'].to_i + 1
|
23
|
+
config
|
24
|
+
end
|
25
|
+
|
26
|
+
# Starts pcapr_local in separate process
|
27
|
+
def setup
|
28
|
+
config = self.config
|
29
|
+
host = config['app']['host']
|
30
|
+
port = config['app']['port']
|
31
|
+
@url_base = "http://#{host}:#{port}"
|
32
|
+
|
33
|
+
# Extract test pcaps and indexes
|
34
|
+
FileUtils.rm_rf '/tmp/pcapr_local_test'
|
35
|
+
test_tar = File.join(File.expand_path(File.dirname(__FILE__)), 'test.tgz')
|
36
|
+
if File.exist? test_tar
|
37
|
+
puts `tar -C /tmp/ -xzf #{test_tar}`
|
38
|
+
end
|
39
|
+
|
40
|
+
# Recreate test database.
|
41
|
+
begin
|
42
|
+
couch = config['couch']
|
43
|
+
RestClient.delete "#{couch['uri']}/#{couch['database']}"
|
44
|
+
rescue RestClient::ResourceNotFound
|
45
|
+
end
|
46
|
+
db = PcaprLocal.get_db config
|
47
|
+
|
48
|
+
# And restore it from datafile.
|
49
|
+
if self.datafile
|
50
|
+
load_docs self.datafile, db
|
51
|
+
end
|
52
|
+
|
53
|
+
# Start server.
|
54
|
+
config_file = Tempfile.new "config"
|
55
|
+
config_file.print config.to_json
|
56
|
+
config_file.flush
|
57
|
+
@pid = fork do
|
58
|
+
Process.setpgid $$, $$
|
59
|
+
exec "#{PcaprLocal::ROOT}/bin/startpcapr -f #{config_file.path} -d"
|
60
|
+
end
|
61
|
+
|
62
|
+
# And wait for it to be ready.
|
63
|
+
wait_for_server host, port
|
64
|
+
end
|
65
|
+
|
66
|
+
def wait_for_server host, port, time=10
|
67
|
+
stop = Time.new + time
|
68
|
+
while Time.new < stop
|
69
|
+
if s = TCPSocket.open(host, port) rescue nil
|
70
|
+
s.close
|
71
|
+
return
|
72
|
+
end
|
73
|
+
sleep 0.01
|
74
|
+
end
|
75
|
+
|
76
|
+
raise "Server at #{host}:#{port} took longer than #{time} seconds to start"
|
77
|
+
end
|
78
|
+
|
79
|
+
def teardown
|
80
|
+
# stop server
|
81
|
+
if @pid
|
82
|
+
Process.kill -2, @pid
|
83
|
+
Process.wait @pid
|
84
|
+
@pid = nil
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def load_docs doc_file, db
|
89
|
+
open doc_file do |js|
|
90
|
+
while line = js.gets
|
91
|
+
doc = JSON.parse line
|
92
|
+
doc.delete '_rev'
|
93
|
+
db.save_doc doc, true
|
94
|
+
end
|
95
|
+
|
96
|
+
db.bulk_save
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def assert_json s1, s2, msg=nil
|
101
|
+
o1 = JSON.parse s1
|
102
|
+
o2 = JSON.parse s2
|
103
|
+
|
104
|
+
if o1.is_a? Hash
|
105
|
+
o1.delete "_rev"
|
106
|
+
end
|
107
|
+
|
108
|
+
if o2.is_a? Hash
|
109
|
+
o2.delete "_rev"
|
110
|
+
end
|
111
|
+
|
112
|
+
assert_equal o1, o2, msg
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
class CouchTestBasic < Test::Unit::TestCase
|
117
|
+
include CouchTest
|
118
|
+
|
119
|
+
def datafile
|
120
|
+
File.join(File.dirname(__FILE__), 'data.js')
|
121
|
+
end
|
122
|
+
|
123
|
+
def test_basic
|
124
|
+
# Main page
|
125
|
+
r = RestClient.get @url_base
|
126
|
+
assert_match "pcapr.Local", r
|
127
|
+
|
128
|
+
# Status
|
129
|
+
r = RestClient.get "#{@url_base}/pcaps/1/status"
|
130
|
+
assert_equal '{"indexed,1292981418000":3}', r
|
131
|
+
|
132
|
+
# Statistics
|
133
|
+
r = RestClient.get "#{@url_base}/pcaps/1/statistics"
|
134
|
+
assert_json '{"packets":52,"bytes":14479,"services":14,"flows":9,"pcaps":3}', r
|
135
|
+
|
136
|
+
# List
|
137
|
+
list = {
|
138
|
+
'date' => %q{{"rows":[{"id":"6808db6ca2264c01780e7fb4fb5c9022","value":null,"key":1292981418000},{"id":"6808db6ca2264c01780e7fb4fb5c9ada","value":null,"key":1292981418000},{"id":"6808db6ca2264c01780e7fb4fb5ca623","value":null,"key":1292981418000}],"offset":0,"total_rows":3}},
|
139
|
+
'path' => %q{{"rows":[{"value":3,"key":null}]}},
|
140
|
+
'status' => %q{{"rows":[{"value":3,"key":null}]}},
|
141
|
+
'service' => %q{{"rows":[{"value":14,"key":null}]}},
|
142
|
+
'keyword' => %q{{"rows":[{"value":7,"key":null}]}},
|
143
|
+
'filename' => %q{{"rows":[{"id":"6808db6ca2264c01780e7fb4fb5ca623","value":null,"key":"A1.pcap"},{"id":"6808db6ca2264c01780e7fb4fb5c9022","value":null,"key":"arp.pcap"},{"id":"6808db6ca2264c01780e7fb4fb5c9ada","value":null,"key":"sip_signalled_call_1.pcap"}],"offset":0,"total_rows":3}},
|
144
|
+
'directory' => %q{{"rows":[{"value":3,"key":null}]}}
|
145
|
+
}
|
146
|
+
|
147
|
+
r = RestClient.get "#{@url_base}/pcaps/1/list"
|
148
|
+
assert_json list['date'], r
|
149
|
+
|
150
|
+
list.keys.each do |key|
|
151
|
+
r = RestClient.get "#{@url_base}/pcaps/1/list?by=#{key}"
|
152
|
+
assert_json list[key], r, "unexpected result when listing by key '#{key}'"
|
153
|
+
end
|
154
|
+
|
155
|
+
# About
|
156
|
+
r = RestClient.get "#{@url_base}/pcaps/1/about/6808db6ca2264c01780e7fb4fb5c9ada"
|
157
|
+
assert_json %q{{"status":"indexed","updated_at":"2010/12/22 01:30:26 +0000","_id":"6808db6ca2264c01780e7fb4fb5c9ada","_rev":"1-2fcf4b207c34b4928bf08945a084a1e7","type":"pcap","filename":"sip_signalled_call_1.pcap","index":{"about":{"packets":22,"hosts":5,"version":"4.5.41604","services":6,"flows":4,"duration":6.29398},"services":["arp","sip/sdp","sip","rtcp","rtp","icmp"]},"stat":{"inode":6395187,"size":5039,"ctime":"2010/12/21 02:04:04 +0000"},"created_at":"2010/12/22 01:30:18 +0000"}}, r
|
158
|
+
|
159
|
+
# Remove
|
160
|
+
r = RestClient.get "#{@url_base}/pcaps/1/remove/6808db6ca2264c01780e7fb4fb5c9ada"
|
161
|
+
assert_json %q{{"error":true,"reason":"status is not failed"}}, r
|
162
|
+
|
163
|
+
# Explore on pcapr
|
164
|
+
r = RestClient.get "#{@url_base}/pcaps/1/pcap/6808db6ca2264c01780e7fb4fb5c9ada"
|
165
|
+
assert_match /pcapr/, r, "Doesn't look like we got redirected to pcapr"
|
166
|
+
|
167
|
+
# Forward to xtractr API
|
168
|
+
r = RestClient.get "#{@url_base}/pcaps/1/pcap/6808db6ca2264c01780e7fb4fb5c9ada/api/fields"
|
169
|
+
assert_equal %q{["pkt.src","pkt.dst","pkt.flow","pkt.id","pkt.pcap","pkt.first","pkt.dir","pkt.time","pkt.offset","pkt.length","pkt.service","pkt.title","arp.dst.hw.mac","arp.hw.size","arp.hw.type","arp.isgratuitous","arp.opcode","arp.proto.size","arp.proto.type","arp.src.hw.mac","eth.addr","eth.dst","eth.ig","eth.lg","eth.src","eth.type","icmp.code","icmp.type","ip.dsfield","ip.dsfield.ce","ip.dsfield.dscp","ip.dsfield.ect","ip.dst.host","ip.flags","ip.flags.df","ip.flags.mf","ip.flags.rb","ip.frag.offset","ip.hdr.len","ip.host","ip.id","ip.len","ip.proto","ip.src.host","ip.ttl","ip.version","rtcp.length","rtcp.length.check","rtcp.padding","rtcp.pt","rtcp.rc","rtcp.sc","rtcp.sdes.length","rtcp.sdes.text","rtcp.sdes.type","rtcp.sender.octetcount","rtcp.sender.packetcount","rtcp.senderssrc","rtcp.setup.frame","rtcp.setup.method","rtcp.ssrc.cum.nr","rtcp.ssrc.dlsr","rtcp.ssrc.ext.high","rtcp.ssrc.fraction","rtcp.ssrc.high.cycles","rtcp.ssrc.high.seq","rtcp.ssrc.identifier","rtcp.ssrc.jitter","rtcp.ssrc.lsr","rtcp.timestamp.ntp","rtcp.timestamp.ntp.lsw","rtcp.timestamp.ntp.msw","rtcp.timestamp.rtp","rtcp.version","rtp.cc","rtp.ext","rtp.extseq","rtp.marker","rtp.p.type","rtp.padding","rtp.seq","rtp.setup.frame","rtp.setup.method","rtp.ssrc","rtp.timestamp","rtp.version","sdp.connection.info","sdp.connection.info.address","sdp.connection.info.address.type","sdp.fmtp.parameter","sdp.media","sdp.media.attr","sdp.media.attribute.field","sdp.media.attribute.value","sdp.media.format","sdp.media.media","sdp.media.port","sdp.media.proto","sdp.mime.type","sdp.owner","sdp.owner.address","sdp.owner.address.type","sdp.owner.sessionid","sdp.owner.username","sdp.owner.version","sdp.sample.rate","sdp.session.name","sdp.time","sdp.time.start","sdp.time.stop","sdp.version","sip.allow","sip.call.id","sip.contact","sip.content.length","sip.content.type","sip.cseq","sip.cseq.method","sip.cseq.seq","sip.from.addr","sip.from.host","sip.from.user","sip.max.forwards","sip.method","sip.msg.hdr","sip.r.uri","sip.r.uri.host","sip.r.uri.user","sip.release.time","sip.request.line","sip.resend","sip.response.request","sip.response.time","sip.server","sip.status.code","sip.status.line","sip.supported","sip.tag","sip.to","sip.to.addr","sip.to.host","sip.to.user","sip.user.agent","sip.via","udp.dstport","udp.length","udp.port","udp.srcport"]}, r
|
170
|
+
|
171
|
+
# Export to zip
|
172
|
+
zip = RestClient.get "#{@url_base}/pcaps/1/export_to_par/6808db6ca2264c01780e7fb4fb5c9ada"
|
173
|
+
Tempfile.open 'zip' do |io|
|
174
|
+
io.write zip
|
175
|
+
io.flush
|
176
|
+
unzip = `unzip -l #{io.path} |awk '{print $4}'`
|
177
|
+
assert_equal "\nName\n----\nabout\npdml\npsml\nfields\npackets.dump\nnormalized.pcap\n\n\n", unzip
|
178
|
+
end
|
179
|
+
|
180
|
+
end
|
181
|
+
end
|
Binary file
|
@@ -0,0 +1,241 @@
|
|
1
|
+
# http://www.mudynamics.com
|
2
|
+
# http://labs.mudynamics.com
|
3
|
+
# http://www.pcapr.net
|
4
|
+
|
5
|
+
require 'mu/testcase'
|
6
|
+
require 'pcapr_local'
|
7
|
+
require 'test/pcapr_local/testcase'
|
8
|
+
|
9
|
+
module PcaprLocal
|
10
|
+
class Scanner
|
11
|
+
|
12
|
+
class Test < ::PcaprLocal::Test::TestCase
|
13
|
+
|
14
|
+
class FakeXtractr
|
15
|
+
def index pcap_path, index_dir
|
16
|
+
FileUtils.mkdir_p "#{index_dir}/terms.db"
|
17
|
+
FileUtils.touch "#{index_dir}/packets.db"
|
18
|
+
FileUtils.touch "#{index_dir}/terms.db/segments"
|
19
|
+
FileUtils.touch "#{index_dir}/terms.db/segments_0"
|
20
|
+
return { "fake summary" => 'blah, blah, blah' }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
PCAP = File.expand_path File.join(File.dirname(__FILE__), "arp.pcap")
|
25
|
+
|
26
|
+
def test_find_pcaps
|
27
|
+
do_setup
|
28
|
+
|
29
|
+
xtractr = FakeXtractr.new
|
30
|
+
config = {
|
31
|
+
"db" => @db,
|
32
|
+
"xtractr" => xtractr,
|
33
|
+
"index_dir" => @index_dir,
|
34
|
+
"pcap_dir" => @pcap_dir,
|
35
|
+
"queue_delay" => 0,
|
36
|
+
"interval" => 0,
|
37
|
+
}
|
38
|
+
scanner = Scanner.new config
|
39
|
+
|
40
|
+
# No pcaps
|
41
|
+
expected = Set.new
|
42
|
+
assert_equal Set.new, scanner.find_pcaps
|
43
|
+
|
44
|
+
# One pcap
|
45
|
+
FileUtils.cp PCAP, "#{@pcap_dir}/foo.pcap"
|
46
|
+
expected << 'foo.pcap'
|
47
|
+
assert_equal expected, scanner.find_pcaps
|
48
|
+
|
49
|
+
# Another
|
50
|
+
FileUtils.cp PCAP, "#{@pcap_dir}/bar.cap"
|
51
|
+
expected << 'bar.cap'
|
52
|
+
assert_equal expected, scanner.find_pcaps
|
53
|
+
|
54
|
+
# Ignore files that don't end in ".pcap" or ".cap"
|
55
|
+
FileUtils.cp PCAP, "#{@pcap_dir}/mypcap"
|
56
|
+
assert_equal expected, scanner.find_pcaps
|
57
|
+
|
58
|
+
# Should Find pcap in sub directory.
|
59
|
+
FileUtils.mkdir_p "#{@pcap_dir}/a/b/c/d"
|
60
|
+
assert_equal expected, scanner.find_pcaps
|
61
|
+
FileUtils.cp PCAP, "#{@pcap_dir}/a/b/c/d/foo.pcap"
|
62
|
+
expected << "a/b/c/d/foo.pcap"
|
63
|
+
assert_equal expected, scanner.find_pcaps
|
64
|
+
|
65
|
+
# Should not look into dir whose name begins with a "."
|
66
|
+
FileUtils.mkdir_p "#{@pcap_dir}/a/b/c/.d"
|
67
|
+
assert_equal expected, scanner.find_pcaps
|
68
|
+
FileUtils.cp PCAP, "#{@pcap_dir}/a/b/c/.d/foo.pcap"
|
69
|
+
assert_equal expected, scanner.find_pcaps
|
70
|
+
|
71
|
+
# Should handle subdir not searchable.
|
72
|
+
system "chmod a-r #{@pcap_dir}/a/b"
|
73
|
+
expected.delete "a/b/c/d/foo.pcap"
|
74
|
+
assert_equal expected, scanner.find_pcaps
|
75
|
+
system "chmod a+r #{@pcap_dir}/a/b"
|
76
|
+
expected << "a/b/c/d/foo.pcap"
|
77
|
+
|
78
|
+
# Should handle dir not searchable.
|
79
|
+
system "chmod a-rx #{@pcap_dir}"
|
80
|
+
assert_equal Set.new, scanner.find_pcaps
|
81
|
+
system "chmod a+rx #{@pcap_dir}"
|
82
|
+
|
83
|
+
# Should handle dir not searchable.
|
84
|
+
system "chmod a-x #{@pcap_dir}"
|
85
|
+
assert_equal Set.new, scanner.find_pcaps
|
86
|
+
system "chmod a+x #{@pcap_dir}"
|
87
|
+
|
88
|
+
# Should handle dir not searchable.
|
89
|
+
system "chmod a-r #{@pcap_dir}"
|
90
|
+
assert_equal Set.new, scanner.find_pcaps
|
91
|
+
system "chmod a+r #{@pcap_dir}"
|
92
|
+
|
93
|
+
# Should return empty set if directory is missing.
|
94
|
+
dir = "/tmp/test#{rand}#{$$}"
|
95
|
+
config['pcap_dir'] = dir
|
96
|
+
scanner = Scanner.new config
|
97
|
+
expected = Set.new
|
98
|
+
assert_equal expected, scanner.find_pcaps
|
99
|
+
|
100
|
+
# Should return empty set if directory is not searchable
|
101
|
+
assert_equal expected, scanner.find_pcaps
|
102
|
+
dir = "/tmp/test#{rand}#{$$}"
|
103
|
+
config['pcap_dir'] = dir
|
104
|
+
scanner = Scanner.new config
|
105
|
+
expected = Set.new
|
106
|
+
assert_equal expected, scanner.find_pcaps
|
107
|
+
ensure
|
108
|
+
system "chmod -R a+rx #{@pcap_dir}"
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_remove_index_for
|
112
|
+
do_setup
|
113
|
+
|
114
|
+
config = {
|
115
|
+
"index_dir" => @index_dir,
|
116
|
+
"reaper_interval" => 60,
|
117
|
+
"idle_timeout" => 60,
|
118
|
+
}
|
119
|
+
xtractr = Xtractr.new config
|
120
|
+
|
121
|
+
config = {
|
122
|
+
"db" => @db,
|
123
|
+
"xtractr" => xtractr,
|
124
|
+
"index_dir" => @index_dir,
|
125
|
+
"pcap_dir" => @pcap_dir,
|
126
|
+
"queue_delay" => 0,
|
127
|
+
"interval" => 0,
|
128
|
+
}
|
129
|
+
scanner = Scanner.new config
|
130
|
+
|
131
|
+
FileUtils.cp PCAP, "#{@pcap_dir}/foo.pcap"
|
132
|
+
|
133
|
+
# Create index
|
134
|
+
index_data = xtractr.index "#{@pcap_dir}/foo.pcap", "#{@index_dir}/foo.pcap"
|
135
|
+
assert File.directory? "#{@index_dir}/foo.pcap"
|
136
|
+
# Remove it
|
137
|
+
scanner.remove_index_for "foo.pcap"
|
138
|
+
assert_equal false, File.exist?("#{@index_dir}/foo.pcap")
|
139
|
+
|
140
|
+
# Create index with extra file, index should not be removed.
|
141
|
+
index_data = xtractr.index "#{@pcap_dir}/foo.pcap", "#{@index_dir}/foo.pcap"
|
142
|
+
FileUtils.touch "#{@index_dir}/foo.pcap/extra_file"
|
143
|
+
assert File.directory? "#{@index_dir}/foo.pcap"
|
144
|
+
scanner.remove_index_for "foo.pcap"
|
145
|
+
assert File.directory? "#{@index_dir}/foo.pcap"
|
146
|
+
FileUtils.rm_rf "#{@index_dir}/foo.pcap"
|
147
|
+
end
|
148
|
+
|
149
|
+
def test_basics
|
150
|
+
do_setup
|
151
|
+
|
152
|
+
xtractr = FakeXtractr.new
|
153
|
+
config = {
|
154
|
+
"db" => @db,
|
155
|
+
"xtractr" => xtractr,
|
156
|
+
"index_dir" => @index_dir,
|
157
|
+
"pcap_dir" => @pcap_dir,
|
158
|
+
"queue_delay" => 0,
|
159
|
+
"interval" => 0,
|
160
|
+
}
|
161
|
+
scanner = Scanner.new config
|
162
|
+
expected = ['.', '..']
|
163
|
+
|
164
|
+
# No pcaps, No indexes
|
165
|
+
scanner.scan
|
166
|
+
assert_equal expected.sort, Dir.entries(@index_dir).sort
|
167
|
+
|
168
|
+
# One pcap added. Create one index.
|
169
|
+
FileUtils.cp PCAP, "#{@pcap_dir}/foo.pcap"
|
170
|
+
scanner.scan
|
171
|
+
expected << "foo.pcap"
|
172
|
+
assert_equal expected.sort, Dir.entries(@index_dir).sort
|
173
|
+
|
174
|
+
# Two additional pcaps. Should have 3 indexes.
|
175
|
+
FileUtils.cp PCAP, "#{@pcap_dir}/bar.pcap"
|
176
|
+
FileUtils.cp PCAP, "#{@pcap_dir}/baz.pcap"
|
177
|
+
expected << "bar.pcap"
|
178
|
+
expected << "baz.pcap"
|
179
|
+
scanner.scan
|
180
|
+
assert_equal expected.sort, Dir.entries(@index_dir).sort
|
181
|
+
|
182
|
+
# Delete an index, It should be recreated.
|
183
|
+
FileUtils.rm_r "#{@index_dir}/bar.pcap"
|
184
|
+
expected.delete "bar.pcap"
|
185
|
+
assert_equal expected.sort, Dir.entries(@index_dir).sort
|
186
|
+
scanner.scan
|
187
|
+
expected << "bar.pcap"
|
188
|
+
assert_equal expected.sort, Dir.entries(@index_dir).sort
|
189
|
+
|
190
|
+
# Remove pcap, index should be removed.
|
191
|
+
File.unlink "#{@pcap_dir}/baz.pcap"
|
192
|
+
expected.delete "baz.pcap"
|
193
|
+
scanner.scan
|
194
|
+
scanner.scan
|
195
|
+
assert_equal expected.sort, Dir.entries(@index_dir).sort
|
196
|
+
|
197
|
+
# Scanner should find pcaps in subdirectory
|
198
|
+
FileUtils.mkdir_p "#{@pcap_dir}/a/b/c/d/"
|
199
|
+
FileUtils.cp PCAP, "#{@pcap_dir}/a/b/c/d/nested.pcap"
|
200
|
+
scanner.scan
|
201
|
+
expected << "a"
|
202
|
+
assert_equal expected.sort, Dir.entries(@index_dir).sort
|
203
|
+
assert File.exist? "#{@index_dir}/a/b/c/d/nested.pcap/terms.db"
|
204
|
+
|
205
|
+
# Pcap should not be indexed until its modification time is older
|
206
|
+
# than queue_delay seconds.
|
207
|
+
delay_sec = 2
|
208
|
+
config['queue_delay'] = delay_sec
|
209
|
+
scanner = Scanner.new config
|
210
|
+
FileUtils.cp PCAP, "#{@pcap_dir}/new.pcap"
|
211
|
+
scanner.scan
|
212
|
+
assert_equal expected.sort, Dir.entries(@index_dir).sort
|
213
|
+
sleep delay_sec + 1
|
214
|
+
scanner.scan
|
215
|
+
expected << "new.pcap"
|
216
|
+
assert_equal expected.sort, Dir.entries(@index_dir).sort
|
217
|
+
|
218
|
+
# Check that database has expected pcaps.
|
219
|
+
expected = [
|
220
|
+
{"id"=>"0dddee3f87f14f1621e5744d667a95b7", "value"=>nil, "key"=>"a/b/c/d/nested.pcap"},
|
221
|
+
{"id"=>"6fc1ee4334c5564563c717bf7ccd734b", "value"=>nil, "key"=>"bar.pcap"},
|
222
|
+
{"id"=>"291eddbc4e2a539e6df74b141ea434f0", "value"=>nil, "key"=>"foo.pcap"},
|
223
|
+
{"id"=>"2517876b6c06c5fdcd4745a14ca96491", "value"=>nil, "key"=>"new.pcap"}
|
224
|
+
]
|
225
|
+
by_filename = []
|
226
|
+
@db.each_in_view 'pcaps/by_filename' do |row|
|
227
|
+
by_filename << row
|
228
|
+
end
|
229
|
+
by_filename.sort_by {|h| h['key']}
|
230
|
+
assert_equal expected, by_filename
|
231
|
+
|
232
|
+
# Check that all pcaps are indexed.
|
233
|
+
@db.each_in_view 'pcaps/by_filename' do |row|
|
234
|
+
doc = @db.get row["id"]
|
235
|
+
assert_equal "indexed", doc.fetch("status")
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
end
|
241
|
+
end
|