dorothy2 0.0.3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,118 @@
1
+ # "THE BEER-WARE LICENSE" (Revision 42):
2
+ # Mu[http://www.mudynamics.com] wrote this file. As long as you retain this
3
+ # notice you can do whatever you want with this stuff. If we meet some day,
4
+ # and you think this stuff is worth it, you can buy us a beer in return.
5
+ #
6
+ # All about pcapr
7
+ # * http://www.pcapr.net
8
+ # * http://groups.google.com/group/pcapr-forum
9
+ # * http://twitter.com/pcapr
10
+ #
11
+ # Mu Dynamics
12
+ # * http://www.mudynamics.com
13
+ # * http://labs.mudynamics.com
14
+
15
+ require 'mu/xtractr'
16
+ require 'test/unit'
17
+
18
+ module Mu
19
+ class Xtractr
20
+ class Views
21
+ class Count
22
+ class Test < Test::Unit::TestCase
23
+ attr_reader :xtractr
24
+ attr_reader :count
25
+
26
+ def setup
27
+ @xtractr = Xtractr.new
28
+ @count = xtractr.flows('flow.service:DNS').count('dns.qry.name').first
29
+ end
30
+
31
+ def test_attributes
32
+ assert_kind_of(Field, count.field)
33
+ assert_equal('ax.search.itunes.apple.com', count.value)
34
+ assert_equal(8, count.count)
35
+ end
36
+
37
+ def test_object
38
+ object = count.object
39
+ assert_kind_of(Field::Value, object)
40
+ assert_equal('dns.qry.name', object.field.name)
41
+ assert_equal('ax.search.itunes.apple.com', object.value)
42
+ end
43
+
44
+ def test_packets
45
+ packets = count.packets
46
+ assert_equal("dns.qry.name:\"ax.search.itunes.apple.com\"", packets.q)
47
+ end
48
+
49
+ def test_each_packet
50
+ count.each_packet do |pkt|
51
+ assert_kind_of(Packet, pkt)
52
+ values = pkt['dns.qry.name']
53
+ assert_equal(1, values.size)
54
+ assert_equal('ax.search.itunes.apple.com', values[0])
55
+ end
56
+ end
57
+
58
+ def test_sum
59
+ sums = count.object.sum('pkt.src', 'pkt.length')
60
+ assert_equal(2, sums.length)
61
+ end
62
+
63
+ def test_inspect
64
+ assert_nothing_raised { count.inspect }
65
+ end
66
+ end
67
+ end # Count
68
+
69
+ class Sum
70
+ class Test < Test::Unit::TestCase
71
+ attr_reader :xtractr
72
+ attr_reader :sum
73
+
74
+ def setup
75
+ @xtractr = Xtractr.new
76
+ @sum = xtractr.flows('flow.service:DNS').sum('dns.qry.name', 'flow.bytes').first
77
+ end
78
+
79
+ def test_attributes
80
+ assert_kind_of(Field, sum.field)
81
+ assert_equal('ax.search.itunes.apple.com', sum.value)
82
+ assert_equal(1220, sum.sum)
83
+ end
84
+
85
+ def test_object
86
+ object = sum.object
87
+ assert_kind_of(Field::Value, object)
88
+ assert_equal('dns.qry.name', object.field.name)
89
+ assert_equal('ax.search.itunes.apple.com', object.value)
90
+ end
91
+
92
+ def test_packets
93
+ packets = sum.packets
94
+ assert_equal("dns.qry.name:\"ax.search.itunes.apple.com\"", packets.q)
95
+ end
96
+
97
+ def test_each_packet
98
+ sum.each_packet do |pkt|
99
+ assert_kind_of(Packet, pkt)
100
+ values = pkt['dns.qry.name']
101
+ assert_equal(1, values.size)
102
+ assert_equal('ax.search.itunes.apple.com', values[0])
103
+ end
104
+ end
105
+
106
+ def test_count
107
+ counts = sum.object.count('pkt.service')
108
+ assert_equal(1, counts.length)
109
+ end
110
+
111
+ def test_inspect
112
+ assert_nothing_raised { sum.inspect }
113
+ end
114
+ end
115
+ end # Sum
116
+ end # Views
117
+ end # Xtractr
118
+ end # Mu
@@ -0,0 +1,151 @@
1
+ # "THE BEER-WARE LICENSE" (Revision 42):
2
+ # Mu[http://www.mudynamics.com] wrote this file. As long as you retain this
3
+ # notice you can do whatever you want with this stuff. If we meet some day,
4
+ # and you think this stuff is worth it, you can buy us a beer in return.
5
+ #
6
+ # All about pcapr
7
+ # * http://www.pcapr.net
8
+ # * http://groups.google.com/group/pcapr-forum
9
+ # * http://twitter.com/pcapr
10
+ #
11
+ # Mu Dynamics
12
+ # * http://www.mudynamics.com
13
+ # * http://labs.mudynamics.com
14
+
15
+ require 'mu/xtractr'
16
+ require 'test/unit'
17
+
18
+ module Mu
19
+ class Xtractr
20
+ class Test < Test::Unit::TestCase
21
+ attr_reader :xtractr
22
+
23
+ def setup
24
+ @xtractr = Xtractr.new
25
+ end
26
+
27
+ def test_about
28
+ about = xtractr.about
29
+ assert_equal(1778, about.packets)
30
+ assert_equal(32, about.flows)
31
+ assert_equal(12, about.hosts)
32
+ assert_equal(5, about.services)
33
+ assert_equal(171.172, about.duration)
34
+ end
35
+
36
+ def test_hosts
37
+ hosts = xtractr.hosts
38
+ assert_equal(12, hosts.size)
39
+ hosts.each { |host| assert_instance_of(Host, host) }
40
+ assert_equal(8, xtractr.hosts(/^8.18/).size)
41
+ assert_equal(8, xtractr.hosts('8.18').size)
42
+ assert_equal(1, xtractr.hosts(/^4.2/).size)
43
+ assert_equal(1, xtractr.hosts('4.2').size)
44
+ end
45
+
46
+ def test_host
47
+ [
48
+ '4.2.2.1',
49
+ '8.18.65.67',
50
+ '8.18.65.32',
51
+ '8.18.65.58',
52
+ '8.18.65.82',
53
+ '8.18.65.27',
54
+ '8.18.65.10',
55
+ '8.18.65.88',
56
+ '8.18.65.89',
57
+ '66.235.132.121',
58
+ '192.168.1.10',
59
+ '224.0.0.251',
60
+ ].each do |address|
61
+ assert_nothing_raised { xtractr.host address }
62
+ end
63
+
64
+ assert_raise(ArgumentError) { xtractr.host '1.1.1.1' }
65
+ end
66
+
67
+ def test_services
68
+ services = xtractr.services
69
+ assert_equal(5, services.size)
70
+ services.each { |service| assert_instance_of(Service, service) }
71
+ assert_equal(2, xtractr.services(/HTTP/).size)
72
+ assert_equal(2, xtractr.services('HTTP').size)
73
+ assert_equal(2, xtractr.services('http').size)
74
+ end
75
+
76
+ def test_service
77
+ [ 'DNS', 'TCP', 'HTTP', 'HTTP/XML', 'MDNS' ].each do |name|
78
+ assert_nothing_raised { xtractr.service name }
79
+ assert_nothing_raised { xtractr.service name.downcase }
80
+ end
81
+
82
+ assert_raise(ArgumentError) { xtractr.service 'blah' }
83
+ end
84
+
85
+ def test_fields
86
+ fields = xtractr.fields
87
+ assert_equal(170, fields.size)
88
+ fields.each { |field| assert_instance_of(Field, field) }
89
+ assert_equal(12, xtractr.fields(/^pkt\./).size)
90
+ assert_equal(12, xtractr.fields("PKT.").size)
91
+ assert_equal(12, xtractr.fields("pkt.").size)
92
+ end
93
+
94
+ def test_field
95
+ [
96
+ 'pkt.src', 'pkt.dst', 'pkt.flow', 'pkt.id', 'pkt.pcap', 'pkt.first',
97
+ 'pkt.dir', 'pkt.time', 'pkt.offset', 'pkt.length', 'pkt.service',
98
+ 'pkt.title'
99
+ ].each do |name|
100
+ assert_nothing_raised { xtractr.field name }
101
+ end
102
+ assert_raise(ArgumentError) { xtractr.field 'blah' }
103
+ end
104
+
105
+ def test_flows
106
+ flows = xtractr.flows
107
+ assert_kind_of(Flows, flows)
108
+ assert_equal('*', flows.q)
109
+
110
+ flows = xtractr.flows 'blah:foo'
111
+ assert_equal('blah:foo', flows.q)
112
+
113
+ flows = xtractr.flows 1..10
114
+ assert_equal('flow.id:[1 10]', flows.q)
115
+
116
+ flows = xtractr.flows 1...10
117
+ assert_equal('flow.id:[1 9]', flows.q)
118
+ end
119
+
120
+ def test_flow
121
+ flow = xtractr.flow 1
122
+ assert_kind_of(Flow, flow)
123
+
124
+ assert_raise(ArgumentError) do
125
+ flow = xtractr.flow xtractr.about.flows+1
126
+ end
127
+ end
128
+
129
+ def test_packets
130
+ packets = xtractr.packets
131
+ assert_kind_of(Packets, packets)
132
+ assert_equal('*', packets.q)
133
+
134
+ packets = xtractr.packets 'blah:foo'
135
+ assert_equal('blah:foo', packets.q)
136
+
137
+ packets = xtractr.packets 1..10
138
+ assert_equal('pkt.id:[1 10]', packets.q)
139
+
140
+ packets = xtractr.packets 1...10
141
+ assert_equal('pkt.id:[1 9]', packets.q)
142
+ end
143
+
144
+ def test_packet
145
+ pkt = xtractr.packet 1
146
+ assert_kind_of(Packet, pkt)
147
+ assert_equal(1, pkt.id)
148
+ end
149
+ end
150
+ end # Xtractr
151
+ end # Mu
@@ -0,0 +1,19 @@
1
+ # "THE BEER-WARE LICENSE" (Revision 42):
2
+ # Mu[http://www.mudynamics.com] wrote this file. As long as you retain this
3
+ # notice you can do whatever you want with this stuff. If we meet some day,
4
+ # and you think this stuff is worth it, you can buy us a beer in return.
5
+ #
6
+ # All about pcapr
7
+ # * http://www.pcapr.net
8
+ # * http://groups.google.com/group/pcapr-forum
9
+ # * http://twitter.com/pcapr
10
+ #
11
+ # Mu Dynamics
12
+ # * http://www.mudynamics.com
13
+ # * http://labs.mudynamics.com
14
+
15
+ require 'test/unit'
16
+
17
+ Dir.glob('mu/xtractr/test/**/tc*.rb').each do |file|
18
+ require file
19
+ end
@@ -0,0 +1,204 @@
1
+ # "THE BEER-WARE LICENSE" (Revision 42):
2
+ # Mu[http://www.mudynamics.com] wrote this file. As long as you retain this
3
+ # notice you can do whatever you want with this stuff. If we meet some day,
4
+ # and you think this stuff is worth it, you can buy us a beer in return.
5
+ #
6
+ # All about pcapr
7
+ # * http://www.pcapr.net
8
+ # * http://groups.google.com/group/pcapr-forum
9
+ # * http://twitter.com/pcapr
10
+ #
11
+ # Mu Dynamics
12
+ # * http://www.mudynamics.com
13
+ # * http://labs.mudynamics.com
14
+
15
+ module Mu
16
+ class Xtractr
17
+ # See http://labs.mudynamics.com/2009/04/03/interactive-couchdb/ for a quick
18
+ # tutorial on how Map/Reduce works.
19
+ class Views # :nodoc:
20
+ # = Count
21
+ # Count contains the results of doing a map/reduce on either flows or
22
+ # packets. Each count contains the field on which the map/reduce was
23
+ # performed, the unique value as all as the count of that value in the
24
+ # flows or packets. For example to count the unique source IP address of
25
+ # HTTP flows in the first five minutes of the index, you would do:
26
+ #
27
+ # xtractr.flows('flow.service:HTTP flow.duration:[1 300]').count('flow.src')
28
+ class Count
29
+ attr_reader :xtractr # :nodoc:
30
+
31
+ # Returns the field used for counting.
32
+ attr_reader :field
33
+
34
+ # Returns the unique value of the field.
35
+ attr_reader :value
36
+
37
+ # Returns the count of the field/value.
38
+ attr_reader :count
39
+
40
+ def initialize xtractr, field, value, count # :nodoc:
41
+ @xtractr = xtractr
42
+ @field = field
43
+ @value = value
44
+ @count = count
45
+ end
46
+
47
+ # Returns a Field::Value object that can be used for further method
48
+ # chaining.
49
+ # xtractr.flows.count('flow.src').first.object.count('flow.service')
50
+ def object
51
+ Field::Value.new xtractr, "key" => field.name, "value" => value
52
+ end
53
+
54
+ # Fetch the list of packets that contain this field value.
55
+ # xtractr.flows.count('flow.src').first.packets.each { |pkt ... }
56
+ def packets q=nil
57
+ object.packets q
58
+ end
59
+
60
+ # Iterate over each packet that contains this field value.
61
+ # xtractr.flows.count('flow.src').first.each_packet { |pkt ... }
62
+ def each_packet(q=nil, &blk) # :yields: packet
63
+ packets(q).each(&blk)
64
+ return self
65
+ end
66
+
67
+ # Sum the numeric values of vfield, keyed by the unique values of
68
+ # kfield. This is used for method chaining.
69
+ # xtractr.flows.count('flow.src').first.sum('flow.service', 'flow.bytes')
70
+ def sum kfield, vfield
71
+ object.sum kfield, vfield
72
+ end
73
+
74
+ def inspect # :nodoc:
75
+ "#<count #{value} #{count}>"
76
+ end
77
+ end
78
+
79
+ # = Sum
80
+ # Sum contains the results of doing a map/reduce on either flows or
81
+ # packets. Each sum contains the field on which the map/reduce was
82
+ # performed, the unique value as all as the sum of that value in the
83
+ # flows or packets. For example to count the bytes sent in HTTP flows
84
+ # keyed by the source IP address, you would do:
85
+ #
86
+ # xtractr.flows('flow.service:HTTP').count('flow.src', 'flow.bytes')
87
+ class Sum
88
+ attr_reader :xtractr # :nodoc:
89
+
90
+ # Returns the field used for summing.
91
+ attr_reader :field
92
+
93
+ # Returns the unique value used as the map/reduce key.
94
+ attr_reader :value
95
+
96
+ # Returns the aggregate computed sum.
97
+ attr_reader :sum
98
+
99
+ def initialize xtractr, field, value, sum # :nodoc:
100
+ @xtractr = xtractr
101
+ @field = field
102
+ @value = value
103
+ @sum = sum
104
+ end
105
+
106
+ # Returns a Field::Value object that can be used for further method
107
+ # chaining. In the following example, we first compute the top talkers
108
+ # (based on the bytes sent) and then use the topmost talker to count
109
+ # the list of unique services.
110
+ # xtractr.flows.sum('flow.src', 'flow.bytes').first.object.count('flow.service')
111
+ def object
112
+ Field::Value.new xtractr, "key" => field.name, "value" => value
113
+ end
114
+
115
+ # Fetch the list of packets that contain this field value.
116
+ # xtractr.flows.sum('flow.src', 'flow.bytes').first.packets.each { |pkt ... }
117
+ def packets q=nil
118
+ object.packets q
119
+ end
120
+
121
+ # Iterate over each packet that contains this field value.
122
+ # xtractr.flows.sum('flow.src', 'flow.bytes').first.each_packet { |pkt ... }
123
+ def each_packet q=nil, &blk
124
+ packets(q).each(&blk)
125
+ return self
126
+ end
127
+
128
+ # Count the unique values of the specified field amongst all the packets
129
+ # that matched the query.
130
+ # xtractr.flows.sum('flow.src', 'flow.bytes').first.count('flow.service')
131
+ def count _field
132
+ object.count _field
133
+ end
134
+
135
+ def inspect # :nodoc:
136
+ "#<sum #{value} #{sum}>"
137
+ end
138
+ end
139
+
140
+ def self.count xtractr, field, url, opts={} # :nodoc:
141
+ field = Field.new(xtractr, field) if field.is_a? String
142
+ name = field.name.gsub /^(pkt|flow)\./, ''
143
+ _opts = opts.dup
144
+ _opts[:r] = <<-EOS
145
+ ({
146
+ map: function(_pf) {
147
+ _pf.values("#{name}", function(_value) {
148
+ if (_value) {
149
+ if (typeof(_value) === 'string') {
150
+ if (_value.length > 1024) {
151
+ _value = _value.slice(0,1024);
152
+ }
153
+ }
154
+ emit(_value, 1);
155
+ }
156
+ });
157
+ },
158
+ reduce: function(_key, _values) {
159
+ return sum(_values);
160
+ }
161
+ })
162
+ EOS
163
+ result = xtractr.json url, _opts
164
+ result['rows'].map do |row|
165
+ Views::Count.new(xtractr, field, row['key'], row['value'])
166
+ end.sort { |a, b| b.count <=> a.count }
167
+ end
168
+
169
+ def self.sum xtractr, kfield, vfield, url, opts={} # :nodoc:
170
+ kfield = Field.new(xtractr, kfield) if kfield.is_a? String
171
+ vfield = Field.new(xtractr, vfield) if vfield.is_a? String
172
+ kname = kfield.name.gsub /^(pkt|flow)\./, ''
173
+ vname = vfield.name.gsub /^(pkt|flow)\./, ''
174
+ _opts = opts.dup
175
+ _opts[:r] = <<-EOS
176
+ ({
177
+ map: function(_pf) {
178
+ var _key = _pf["#{kname}"];
179
+ if (_key) {
180
+ if (typeof(_key) === 'string') {
181
+ if (_key.length > 1024) {
182
+ _key = _key.slice(0,1024);
183
+ }
184
+ }
185
+ _pf.values("#{vname}", function(_val) {
186
+ if (typeof(_val) === 'number') {
187
+ emit(_key, _val);
188
+ }
189
+ });
190
+ }
191
+ },
192
+ reduce: function(_key, _values) {
193
+ return sum(_values);
194
+ }
195
+ })
196
+ EOS
197
+ result = xtractr.json url, _opts
198
+ result['rows'].map do |row|
199
+ Views::Sum.new(xtractr, kfield, row['key'], row['value'])
200
+ end.sort { |a, b| b.sum <=> a.sum }
201
+ end
202
+ end
203
+ end # Xtractr
204
+ end # Mu