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.
Files changed (203) hide show
  1. data/.document +5 -0
  2. data/LICENSE.txt +20 -0
  3. data/README.md +64 -0
  4. data/Rakefile +57 -0
  5. data/VERSION +1 -0
  6. data/bin/pcap2par +49 -0
  7. data/bin/startpcapr +40 -0
  8. data/bin/stoppcapr +33 -0
  9. data/bin/xtractr +5 -0
  10. data/lib/environment.rb +106 -0
  11. data/lib/exe/xtractr +0 -0
  12. data/lib/mu/pcap.rb +110 -0
  13. data/lib/mu/pcap/ethernet.rb +148 -0
  14. data/lib/mu/pcap/header.rb +75 -0
  15. data/lib/mu/pcap/io_pair.rb +67 -0
  16. data/lib/mu/pcap/io_wrapper.rb +76 -0
  17. data/lib/mu/pcap/ip.rb +61 -0
  18. data/lib/mu/pcap/ipv4.rb +257 -0
  19. data/lib/mu/pcap/ipv6.rb +148 -0
  20. data/lib/mu/pcap/packet.rb +104 -0
  21. data/lib/mu/pcap/pkthdr.rb +155 -0
  22. data/lib/mu/pcap/reader.rb +61 -0
  23. data/lib/mu/pcap/reader/http_family.rb +170 -0
  24. data/lib/mu/pcap/sctp.rb +367 -0
  25. data/lib/mu/pcap/sctp/chunk.rb +123 -0
  26. data/lib/mu/pcap/sctp/chunk/data.rb +134 -0
  27. data/lib/mu/pcap/sctp/chunk/init.rb +100 -0
  28. data/lib/mu/pcap/sctp/chunk/init_ack.rb +68 -0
  29. data/lib/mu/pcap/sctp/parameter.rb +110 -0
  30. data/lib/mu/pcap/sctp/parameter/ip_address.rb +48 -0
  31. data/lib/mu/pcap/stream_packetizer.rb +72 -0
  32. data/lib/mu/pcap/tcp.rb +505 -0
  33. data/lib/mu/pcap/udp.rb +69 -0
  34. data/lib/mu/scenario/pcap.rb +164 -0
  35. data/lib/mu/scenario/pcap/fields.rb +50 -0
  36. data/lib/mu/scenario/pcap/rtp.rb +71 -0
  37. data/lib/pcapr_local.rb +159 -0
  38. data/lib/pcapr_local/config.rb +336 -0
  39. data/lib/pcapr_local/db.rb +197 -0
  40. data/lib/pcapr_local/scanner.rb +250 -0
  41. data/lib/pcapr_local/server.rb +178 -0
  42. data/lib/pcapr_local/www/favicon.ico +0 -0
  43. data/lib/pcapr_local/www/favicon.png +0 -0
  44. data/lib/pcapr_local/www/home/index.html +138 -0
  45. data/lib/pcapr_local/www/static/image/16x16/Cancel.png +0 -0
  46. data/lib/pcapr_local/www/static/image/16x16/Cancel.png.1 +0 -0
  47. data/lib/pcapr_local/www/static/image/16x16/Download.png +0 -0
  48. data/lib/pcapr_local/www/static/image/16x16/Folder3.png +0 -0
  49. data/lib/pcapr_local/www/static/image/16x16/Full Size.png +0 -0
  50. data/lib/pcapr_local/www/static/image/16x16/Minus.png +0 -0
  51. data/lib/pcapr_local/www/static/image/16x16/Plus.png +0 -0
  52. data/lib/pcapr_local/www/static/image/16x16/Search.png +0 -0
  53. data/lib/pcapr_local/www/static/image/16x16/User.png +0 -0
  54. data/lib/pcapr_local/www/static/image/48x48/Phone.png +0 -0
  55. data/lib/pcapr_local/www/static/image/48x48/Video.png +0 -0
  56. data/lib/pcapr_local/www/static/image/bar-orange.gif +0 -0
  57. data/lib/pcapr_local/www/static/image/beta.png +0 -0
  58. data/lib/pcapr_local/www/static/image/bg.png +0 -0
  59. data/lib/pcapr_local/www/static/image/blockquote.png +0 -0
  60. data/lib/pcapr_local/www/static/image/body-bg.png +0 -0
  61. data/lib/pcapr_local/www/static/image/body-h3.png +0 -0
  62. data/lib/pcapr_local/www/static/image/body-hl1-bg.png +0 -0
  63. data/lib/pcapr_local/www/static/image/body-hl1-h3.png +0 -0
  64. data/lib/pcapr_local/www/static/image/body-hl1-readmore.png +0 -0
  65. data/lib/pcapr_local/www/static/image/body-hl2-bg.png +0 -0
  66. data/lib/pcapr_local/www/static/image/body-hl2-h3.png +0 -0
  67. data/lib/pcapr_local/www/static/image/body-hl2-readmore.png +0 -0
  68. data/lib/pcapr_local/www/static/image/body-hl3-bg.png +0 -0
  69. data/lib/pcapr_local/www/static/image/body-hl3-h3.png +0 -0
  70. data/lib/pcapr_local/www/static/image/body-hl3-readmore.png +0 -0
  71. data/lib/pcapr_local/www/static/image/body-hl4-bg.png +0 -0
  72. data/lib/pcapr_local/www/static/image/body-hl4-h3.png +0 -0
  73. data/lib/pcapr_local/www/static/image/body-hl4-readmore.png +0 -0
  74. data/lib/pcapr_local/www/static/image/body-hl5-h3.png +0 -0
  75. data/lib/pcapr_local/www/static/image/body-hl6-h3.png +0 -0
  76. data/lib/pcapr_local/www/static/image/body-hl7-h3.png +0 -0
  77. data/lib/pcapr_local/www/static/image/body-hl8-h3.png +0 -0
  78. data/lib/pcapr_local/www/static/image/body-readmore.png +0 -0
  79. data/lib/pcapr_local/www/static/image/bottom-bg.png +0 -0
  80. data/lib/pcapr_local/www/static/image/bottom-l.png +0 -0
  81. data/lib/pcapr_local/www/static/image/bottom-r.png +0 -0
  82. data/lib/pcapr_local/www/static/image/btn-search.png +0 -0
  83. data/lib/pcapr_local/www/static/image/bullet-1.png +0 -0
  84. data/lib/pcapr_local/www/static/image/bullet-2.png +0 -0
  85. data/lib/pcapr_local/www/static/image/bullet-3.png +0 -0
  86. data/lib/pcapr_local/www/static/image/bullet-4.png +0 -0
  87. data/lib/pcapr_local/www/static/image/bullet-5.png +0 -0
  88. data/lib/pcapr_local/www/static/image/bullet-6.png +0 -0
  89. data/lib/pcapr_local/www/static/image/bullet-7.png +0 -0
  90. data/lib/pcapr_local/www/static/image/bullet-hl1.png +0 -0
  91. data/lib/pcapr_local/www/static/image/bullet-hl2.png +0 -0
  92. data/lib/pcapr_local/www/static/image/bullet-hl3.png +0 -0
  93. data/lib/pcapr_local/www/static/image/bullet-hl4.png +0 -0
  94. data/lib/pcapr_local/www/static/image/bullet-pathway.png +0 -0
  95. data/lib/pcapr_local/www/static/image/bullet-section1.png +0 -0
  96. data/lib/pcapr_local/www/static/image/bullet-section2.png +0 -0
  97. data/lib/pcapr_local/www/static/image/collapsed.gif +0 -0
  98. data/lib/pcapr_local/www/static/image/crosslink.png +0 -0
  99. data/lib/pcapr_local/www/static/image/expanded.gif +0 -0
  100. data/lib/pcapr_local/www/static/image/favicon.ico +0 -0
  101. data/lib/pcapr_local/www/static/image/favicon.png +0 -0
  102. data/lib/pcapr_local/www/static/image/icon-author.png +0 -0
  103. data/lib/pcapr_local/www/static/image/icon-created.png +0 -0
  104. data/lib/pcapr_local/www/static/image/p-expand.gif +0 -0
  105. data/lib/pcapr_local/www/static/image/pcapr-logo.png +0 -0
  106. data/lib/pcapr_local/www/static/image/powered-by.png +0 -0
  107. data/lib/pcapr_local/www/static/image/section1-bg.png +0 -0
  108. data/lib/pcapr_local/www/static/image/section1-h3.png +0 -0
  109. data/lib/pcapr_local/www/static/image/section1-readmore.png +0 -0
  110. data/lib/pcapr_local/www/static/image/section2-bg.png +0 -0
  111. data/lib/pcapr_local/www/static/image/section2-h3.png +0 -0
  112. data/lib/pcapr_local/www/static/image/section2-readmore.png +0 -0
  113. data/lib/pcapr_local/www/static/image/status-alert.png +0 -0
  114. data/lib/pcapr_local/www/static/image/status-download.png +0 -0
  115. data/lib/pcapr_local/www/static/image/status-info.png +0 -0
  116. data/lib/pcapr_local/www/static/image/status-note.png +0 -0
  117. data/lib/pcapr_local/www/static/image/tab-round.png +0 -0
  118. data/lib/pcapr_local/www/static/image/throbber.gif +0 -0
  119. data/lib/pcapr_local/www/static/image/user.jpg +0 -0
  120. data/lib/pcapr_local/www/static/script/closet/async.js +421 -0
  121. data/lib/pcapr_local/www/static/script/closet/closet.api.js +241 -0
  122. data/lib/pcapr_local/www/static/script/closet/closet.folders.js +94 -0
  123. data/lib/pcapr_local/www/static/script/closet/closet.js +187 -0
  124. data/lib/pcapr_local/www/static/script/closet/closet.mr.js +219 -0
  125. data/lib/pcapr_local/www/static/script/closet/closet.options.js +359 -0
  126. data/lib/pcapr_local/www/static/script/closet/closet.quantity.js +73 -0
  127. data/lib/pcapr_local/www/static/script/closet/closet.render.js +205 -0
  128. data/lib/pcapr_local/www/static/script/closet/closet.report.js +86 -0
  129. data/lib/pcapr_local/www/static/script/closet/closet.reports.http.js +135 -0
  130. data/lib/pcapr_local/www/static/script/closet/closet.reports.overview.js +163 -0
  131. data/lib/pcapr_local/www/static/script/closet/closet.reports.sip.js +159 -0
  132. data/lib/pcapr_local/www/static/script/closet/closet.reports.tcp.js +72 -0
  133. data/lib/pcapr_local/www/static/script/closet/closet.reports.visualize.js +263 -0
  134. data/lib/pcapr_local/www/static/script/closet/closet.util.js +40 -0
  135. data/lib/pcapr_local/www/static/script/jquery/jquery-1.4.2.min.js +154 -0
  136. data/lib/pcapr_local/www/static/script/jquery/jquery-ui.js +10921 -0
  137. data/lib/pcapr_local/www/static/script/jquery/jquery.flot.js +2123 -0
  138. data/lib/pcapr_local/www/static/script/jquery/jquery.flot.selection.js +184 -0
  139. data/lib/pcapr_local/www/static/script/jquery/jquery.flot.stack.js +184 -0
  140. data/lib/pcapr_local/www/static/script/jquery/jquery.form.js +643 -0
  141. data/lib/pcapr_local/www/static/script/jquery/jquery.jsonp.min.js +3 -0
  142. data/lib/pcapr_local/www/static/script/jquery/jquery.menu.js +142 -0
  143. data/lib/pcapr_local/www/static/script/jquery/jquery.suggest.js +308 -0
  144. data/lib/pcapr_local/www/static/script/jquery/jquery.ui.core.js +203 -0
  145. data/lib/pcapr_local/www/static/script/jquery/jquery.ui.slider.js +629 -0
  146. data/lib/pcapr_local/www/static/script/jquery/jquery.ui.sortable.js +1055 -0
  147. data/lib/pcapr_local/www/static/script/jquery/jquery.ui.widget.js +236 -0
  148. data/lib/pcapr_local/www/static/script/json2.js +481 -0
  149. data/lib/pcapr_local/www/static/script/sammy/plugins/sammy.cache.js +115 -0
  150. data/lib/pcapr_local/www/static/script/sammy/plugins/sammy.template.js +117 -0
  151. data/lib/pcapr_local/www/static/script/sammy/sammy.js +1696 -0
  152. data/lib/pcapr_local/www/static/script/tipsy/jquery.tipsy.js +104 -0
  153. data/lib/pcapr_local/www/static/style/c3p0.css +116 -0
  154. data/lib/pcapr_local/www/static/style/jquery.suggest.css +27 -0
  155. data/lib/pcapr_local/www/static/style/page.css +1113 -0
  156. data/lib/pcapr_local/www/static/style/tipsy.css +7 -0
  157. data/lib/pcapr_local/www/templates/browse.services.template +10 -0
  158. data/lib/pcapr_local/www/templates/browse.template +77 -0
  159. data/lib/pcapr_local/www/templates/flows.template +38 -0
  160. data/lib/pcapr_local/www/templates/pcap.template +63 -0
  161. data/lib/pcapr_local/www/templates/sip.calls.template +35 -0
  162. data/lib/pcapr_local/www/templates/statistics.template +6 -0
  163. data/lib/pcapr_local/xtractr.rb +179 -0
  164. data/lib/pcapr_local/xtractr/instance.rb +172 -0
  165. data/pcapr-local.gemspec +297 -0
  166. data/test/mu/pcap/reader/tc_http_family.rb +251 -0
  167. data/test/mu/pcap/tc_ethernet.rb +71 -0
  168. data/test/mu/pcap/tc_header.rb +56 -0
  169. data/test/mu/pcap/tc_ipv4.rb +103 -0
  170. data/test/mu/pcap/tc_ipv6.rb +83 -0
  171. data/test/mu/pcap/tc_packet.rb +44 -0
  172. data/test/mu/pcap/tc_pair.rb +58 -0
  173. data/test/mu/pcap/tc_pkthdr.rb +33 -0
  174. data/test/mu/pcap/tc_reader.rb +76 -0
  175. data/test/mu/pcap/tc_tcp.rb +426 -0
  176. data/test/mu/pcap/tc_udp.rb +33 -0
  177. data/test/mu/pcap/tc_wrapper.rb +80 -0
  178. data/test/mu/scenario/pcap/tc_fields.rb +67 -0
  179. data/test/mu/scenario/pcap/tc_rtp.rb +135 -0
  180. data/test/mu/scenario/sip_signalled_call_1.pcap +0 -0
  181. data/test/mu/scenario/tc_pcap.rb +190 -0
  182. data/test/mu/scenario/test_data/arp.pcap +0 -0
  183. data/test/mu/scenario/test_data/dns.pcap +0 -0
  184. data/test/mu/scenario/test_data/http-v6.pcap +0 -0
  185. data/test/mu/scenario/test_data/http.pcap +0 -0
  186. data/test/mu/scenario/test_data/http_chunked.pcap +0 -0
  187. data/test/mu/scenario/test_data/http_deflate.pcap +0 -0
  188. data/test/mu/scenario/test_data/httpauth3.pcap +0 -0
  189. data/test/mu/scenario/test_data/icmp.pcap +0 -0
  190. data/test/mu/scenario/test_data/sip_signalled_call_1.pcap +0 -0
  191. data/test/mu/tc_pcap.rb +39 -0
  192. data/test/mu/testcase.rb +86 -0
  193. data/test/pcapr_local/arp.pcap +0 -0
  194. data/test/pcapr_local/data.js +3 -0
  195. data/test/pcapr_local/http_chunked.pcap +0 -0
  196. data/test/pcapr_local/tc_api.rb +181 -0
  197. data/test/pcapr_local/test.tgz +0 -0
  198. data/test/pcapr_local/test_scanner.rb +241 -0
  199. data/test/pcapr_local/test_xtractr.rb +219 -0
  200. data/test/pcapr_local/testcase.rb +107 -0
  201. data/test/test_export_to_scenario.sh +25 -0
  202. data/test/test_pcapr_local.rb +29 -0
  203. 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
@@ -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