packetfu 1.1.9 → 1.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/bench/octets.rb +9 -9
- data/examples/100kpackets.rb +12 -12
- data/examples/ackscan.rb +16 -16
- data/examples/arp.rb +35 -35
- data/examples/arphood.rb +36 -36
- data/examples/dissect_thinger.rb +6 -6
- data/examples/new-simple-stats.rb +23 -23
- data/examples/packetfu-shell.rb +25 -25
- data/examples/simple-sniffer.rb +9 -9
- data/examples/simple-stats.rb +23 -23
- data/examples/slammer.rb +3 -3
- data/lib/packetfu.rb +127 -127
- data/lib/packetfu/capture.rb +169 -169
- data/lib/packetfu/config.rb +52 -52
- data/lib/packetfu/inject.rb +56 -56
- data/lib/packetfu/packet.rb +528 -528
- data/lib/packetfu/pcap.rb +579 -579
- data/lib/packetfu/protos/arp.rb +90 -90
- data/lib/packetfu/protos/arp/header.rb +158 -158
- data/lib/packetfu/protos/arp/mixin.rb +36 -36
- data/lib/packetfu/protos/eth.rb +44 -44
- data/lib/packetfu/protos/eth/header.rb +243 -243
- data/lib/packetfu/protos/eth/mixin.rb +3 -3
- data/lib/packetfu/protos/hsrp.rb +69 -69
- data/lib/packetfu/protos/hsrp/header.rb +107 -107
- data/lib/packetfu/protos/hsrp/mixin.rb +29 -29
- data/lib/packetfu/protos/icmp.rb +71 -71
- data/lib/packetfu/protos/icmp/header.rb +82 -82
- data/lib/packetfu/protos/icmp/mixin.rb +14 -14
- data/lib/packetfu/protos/invalid.rb +49 -49
- data/lib/packetfu/protos/ip.rb +69 -69
- data/lib/packetfu/protos/ip/header.rb +291 -291
- data/lib/packetfu/protos/ip/mixin.rb +40 -40
- data/lib/packetfu/protos/ipv6.rb +50 -50
- data/lib/packetfu/protos/ipv6/header.rb +188 -188
- data/lib/packetfu/protos/ipv6/mixin.rb +29 -29
- data/lib/packetfu/protos/tcp.rb +176 -176
- data/lib/packetfu/protos/tcp/ecn.rb +35 -35
- data/lib/packetfu/protos/tcp/flags.rb +74 -74
- data/lib/packetfu/protos/tcp/header.rb +268 -268
- data/lib/packetfu/protos/tcp/hlen.rb +32 -32
- data/lib/packetfu/protos/tcp/mixin.rb +46 -46
- data/lib/packetfu/protos/tcp/option.rb +321 -321
- data/lib/packetfu/protos/tcp/options.rb +95 -95
- data/lib/packetfu/protos/tcp/reserved.rb +35 -35
- data/lib/packetfu/protos/udp.rb +116 -116
- data/lib/packetfu/protos/udp/header.rb +91 -91
- data/lib/packetfu/protos/udp/mixin.rb +3 -3
- data/lib/packetfu/structfu.rb +280 -280
- data/lib/packetfu/utils.rb +226 -217
- data/lib/packetfu/version.rb +41 -41
- data/packetfu.gemspec +2 -1
- data/spec/ethpacket_spec.rb +48 -48
- data/spec/packet_spec.rb +57 -57
- data/spec/packet_subclasses_spec.rb +8 -8
- data/spec/packetfu_spec.rb +59 -59
- data/spec/structfu_spec.rb +268 -268
- data/spec/tcp_spec.rb +75 -75
- data/test/all_tests.rb +13 -13
- data/test/func_lldp.rb +3 -3
- data/test/ptest.rb +2 -2
- data/test/test_arp.rb +116 -116
- data/test/test_capture.rb +45 -45
- data/test/test_eth.rb +68 -68
- data/test/test_hsrp.rb +9 -9
- data/test/test_icmp.rb +52 -52
- data/test/test_inject.rb +18 -18
- data/test/test_invalid.rb +16 -16
- data/test/test_ip.rb +36 -36
- data/test/test_ip6.rb +48 -48
- data/test/test_octets.rb +21 -21
- data/test/test_packet.rb +154 -154
- data/test/test_pcap.rb +170 -170
- data/test/test_structfu.rb +97 -97
- data/test/test_tcp.rb +320 -320
- data/test/test_udp.rb +76 -76
- metadata +4 -3
data/examples/simple-stats.rb
CHANGED
@@ -16,33 +16,33 @@ require 'packetfu'
|
|
16
16
|
# Takes a file name, parses the packets, and records the packet
|
17
17
|
# type based on its PacketFu class.
|
18
18
|
def count_packet_types(file)
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
19
|
+
file = File.open(file) {|f| f.read}
|
20
|
+
stats = {}
|
21
|
+
count = 0
|
22
|
+
pcapfile = PacketFu::PcapPackets.new
|
23
|
+
pcapfile.read(file)
|
24
|
+
pcapfile.each do |p|
|
25
|
+
# Now it's a PacketFu packet struct.
|
26
|
+
pkt = PacketFu::Packet.parse(p.data)
|
27
|
+
kind = pkt.class.to_s.split("::").last
|
28
|
+
if stats[kind]
|
29
|
+
stats[kind] += 1
|
30
|
+
else
|
31
|
+
stats[kind] = 0
|
32
|
+
end
|
33
|
+
count += 1
|
34
|
+
break if count >= 1_000
|
35
|
+
end
|
36
|
+
stats.each_pair { |k,v| puts "%-12s: %4d" % [k,v] }
|
37
37
|
end
|
38
38
|
|
39
39
|
if File.readable?(infile = (ARGV[0] || 'in.pcap'))
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
40
|
+
title = "Packets by packet type in '#{infile}'"
|
41
|
+
puts title
|
42
|
+
puts "-" * title.size
|
43
|
+
count_packet_types(infile)
|
44
44
|
else
|
45
|
-
|
45
|
+
raise RuntimeError, "Need an infile, like so: #{$0} in.pcap"
|
46
46
|
end
|
47
47
|
|
48
48
|
|
data/examples/slammer.rb
CHANGED
@@ -14,7 +14,7 @@ include PacketFu
|
|
14
14
|
slammer = "\004\001\001\001\001\001\001" + "\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001" + "\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001" + "\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001" + "\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\334\311\260B\353\016" + "\001\001\001\001\001\001\001p\256B\001p\256B\220\220\220\220\220\220\220\220h\334\311\260B\270\001\001" + "\001\0011\311\261\030P\342\3755\001\001\001\005P\211\345Qh.dllhel32hkernQhounthickChGetTf" + "\271llQh32.dhws2_f\271etQhsockf\271toQhsend\276\030\020\256B\215E\324P\377\026P\215E\340P\215E\360P\377" + "\026P\276\020\020\256B\213\036\213\003=U\213\354Qt\005\276\034\020\256B\377\026\377\3201\311QQP\201\361" + "\003\001\004\233\201\361\001\001\001\001Q\215E\314P\213E\300P\377\026j\021j\002j\002\377\320P\215E\304P" + "\213E\300P\377\026\211\306\t\333\201\363<a\331\377\213E\264\215\f@\215\024\210\301\342\004\001\302\301" + "\342\b)\302\215\004\220\001\330\211E\264j\020\215E\260P1\311Qf\201\361x\001Q\215E\003P\213E\254P\377\326" + "\353\312"
|
15
15
|
|
16
16
|
def rand_source_ip
|
17
|
-
|
17
|
+
[rand(0xffffffff)].pack("N")
|
18
18
|
end
|
19
19
|
|
20
20
|
kill_packet = UDPPacket.new
|
@@ -26,9 +26,9 @@ kill_packet.recalc
|
|
26
26
|
kill_packet.payload = slammer
|
27
27
|
|
28
28
|
if action == 'file'.downcase
|
29
|
-
|
29
|
+
puts kill_packet.to_f
|
30
30
|
else
|
31
|
-
|
31
|
+
puts kill_packet.to_w(action.downcase)
|
32
32
|
end
|
33
33
|
|
34
34
|
|
data/lib/packetfu.rb
CHANGED
@@ -13,133 +13,133 @@ require 'rubygems' if RUBY_VERSION =~ /^1\.[0-8]/
|
|
13
13
|
|
14
14
|
module PacketFu
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
16
|
+
# Picks up all the protocols defined in the protos subdirectory
|
17
|
+
def self.require_protos(cwd)
|
18
|
+
protos_dir = File.join(cwd, "packetfu", "protos")
|
19
|
+
Dir.new(protos_dir).each do |fname|
|
20
|
+
next unless fname[/\.rb$/]
|
21
|
+
begin
|
22
|
+
require File.join(protos_dir,fname)
|
23
|
+
rescue
|
24
|
+
warn "Warning: Could not load `#{fname}'. Skipping."
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Deal with Ruby's encoding by ignoring it.
|
30
|
+
def self.force_binary(str)
|
31
|
+
str.force_encoding Encoding::BINARY if str.respond_to? :force_encoding
|
32
|
+
end
|
33
|
+
|
34
|
+
# Sets the expected byte order for a pcap file. See PacketFu::Read.set_byte_order
|
35
|
+
@byte_order = :little
|
36
|
+
|
37
|
+
# Checks if pcaprub is loaded correctly.
|
38
|
+
@pcaprub_loaded = false
|
39
|
+
|
40
|
+
# PacketFu works best with Pcaprub version 0.8-dev (at least)
|
41
|
+
# The current (Aug 01, 2010) pcaprub gem is 0.9, so should be fine.
|
42
|
+
def self.pcaprub_platform_require
|
43
|
+
begin
|
44
|
+
require 'pcaprub'
|
45
|
+
rescue LoadError
|
46
|
+
return false
|
47
|
+
end
|
48
|
+
@pcaprub_loaded = true
|
49
|
+
end
|
50
|
+
|
51
|
+
pcaprub_platform_require
|
52
|
+
|
53
|
+
if @pcaprub_loaded
|
54
|
+
pcaprub_regex = /[0-9]\.([8-9]|[1-7][0-9])(-dev)?/ # Regex for 0.8 and beyond.
|
55
|
+
if Pcap.version !~ pcaprub_regex
|
56
|
+
@pcaprub_loaded = false # Don't bother with broken versions
|
57
|
+
raise LoadError, "PcapRub not at a minimum version of 0.8-dev"
|
58
|
+
end
|
59
|
+
require "packetfu/capture"
|
60
|
+
require "packetfu/inject"
|
61
|
+
end
|
62
|
+
|
63
|
+
# Returns the status of pcaprub
|
64
|
+
def self.pcaprub_loaded?
|
65
|
+
@pcaprub_loaded
|
66
|
+
end
|
67
|
+
|
68
|
+
# Returns an array of classes defined in PacketFu
|
69
|
+
def self.classes
|
70
|
+
constants.map { |const| const_get(const) if const_get(const).kind_of? Class}.compact
|
71
|
+
end
|
72
|
+
|
73
|
+
# Adds the class to PacketFu's list of packet classes -- used in packet parsing.
|
74
|
+
def self.add_packet_class(klass)
|
75
|
+
raise "Need a class" unless klass.kind_of? Class
|
76
|
+
if klass.name !~ /[A-Za-z0-9]Packet/
|
77
|
+
raise "Packet classes should be named 'ProtoPacket'"
|
78
|
+
end
|
79
|
+
@packet_classes ||= []
|
80
|
+
@packet_classes << klass
|
81
|
+
@packet_classes_dirty = true
|
82
|
+
@packet_classes.sort! {|x,y| x.name <=> y.name}
|
83
|
+
end
|
84
|
+
|
85
|
+
# Presumably, there may be a time where you'd like to remove a packet class.
|
86
|
+
def self.remove_packet_class(klass)
|
87
|
+
raise "Need a class" unless klass.kind_of? Class
|
88
|
+
@packet_classes ||= []
|
89
|
+
@packet_classes.delete klass
|
90
|
+
@packet_classes_dirty = true
|
91
|
+
@packet_classes
|
92
|
+
end
|
93
|
+
|
94
|
+
# Returns an array of packet classes
|
95
|
+
def self.packet_classes
|
96
|
+
@packet_classes || []
|
97
|
+
end
|
98
|
+
|
99
|
+
# Returns an array of packet types by packet prefix.
|
100
|
+
def self.packet_prefixes
|
101
|
+
return [] if @packet_classes.nil?
|
102
|
+
return @packet_class_prefixes if @packet_classes_dirty == false
|
103
|
+
@packet_classes_dirty = false
|
104
|
+
@packet_class_prefixes = @packet_classes.map {|p| p.to_s.split("::").last.to_s.downcase.gsub(/packet$/,"")}
|
105
|
+
return @packet_class_prefixes
|
106
|
+
end
|
107
|
+
|
108
|
+
# The current inspect style. One of :hex, :dissect, or :default
|
109
|
+
# Note that :default means Ruby's default, which is usually
|
110
|
+
# far too long to be useful.
|
111
|
+
def self.inspect_style
|
112
|
+
@inspect_style ||= :dissect
|
113
|
+
end
|
114
|
+
|
115
|
+
# Setter for PacketFu's @inspect_style
|
116
|
+
def self.inspect_style=(arg)
|
117
|
+
@inspect_style = case arg
|
118
|
+
when :hex, :pretty
|
119
|
+
:hex
|
120
|
+
when :dissect, :verbose
|
121
|
+
:dissect
|
122
|
+
when :default, :ugly
|
123
|
+
:default
|
124
|
+
else
|
125
|
+
:dissect
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# Switches inspect styles in a round-robin fashion between
|
130
|
+
# :dissect, :default, and :hex
|
131
|
+
def toggle_inspect
|
132
|
+
case @inspect_style
|
133
|
+
when :hex, :pretty
|
134
|
+
@inspect_style = :dissect
|
135
|
+
when :dissect, :verbose
|
136
|
+
@inspect_style = :default
|
137
|
+
when :default, :ugly
|
138
|
+
@inspect_style = :hex
|
139
|
+
else
|
140
|
+
@inspect_style = :dissect
|
141
|
+
end
|
142
|
+
end
|
143
143
|
|
144
144
|
|
145
145
|
end
|
data/lib/packetfu/capture.rb
CHANGED
@@ -1,173 +1,173 @@
|
|
1
1
|
# -*- coding: binary -*-
|
2
2
|
module PacketFu
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
4
|
+
# The Capture class is used to construct PcapRub objects in order to collect
|
5
|
+
# packets from an interface.
|
6
|
+
#
|
7
|
+
# This class requires PcapRub. In addition, you will need root (or root-like) privileges
|
8
|
+
# in order to capture from the interface.
|
9
|
+
#
|
10
|
+
# Note, on some wireless cards, setting :promisc => true will disable capturing.
|
11
|
+
#
|
12
|
+
# == Example
|
13
|
+
#
|
14
|
+
# # Typical use
|
15
|
+
# cap = PacketFu::Capture.new(:iface => 'eth0', :promisc => true)
|
16
|
+
# cap.start
|
17
|
+
# sleep 10
|
18
|
+
# cap.save
|
19
|
+
# first_packet = cap.array[0]
|
20
|
+
#
|
21
|
+
# # Tcpdump-like use
|
22
|
+
# cap = PacketFu::Capture.new(:start => true)
|
23
|
+
# cap.show_live(:save => true, :filter => 'tcp and not port 22')
|
24
|
+
#
|
25
|
+
# == See Also
|
26
|
+
#
|
27
|
+
# Read, Write
|
28
|
+
class Capture
|
29
|
+
attr_accessor :array, :stream # Leave these public and open.
|
30
|
+
attr_reader :iface, :snaplen, :promisc, :timeout, :filter
|
31
|
+
|
32
|
+
def initialize(args={})
|
33
|
+
@array = [] # Where the packet array goes.
|
34
|
+
@stream = [] # Where the stream goes.
|
35
|
+
@iface = (args[:iface] || ENV['IFACE'] || Pcap.lookupdev || "lo").to_s
|
36
|
+
@snaplen = args[:snaplen] || 0xffff
|
37
|
+
@promisc = args[:promisc] || false # Sensible for some Intel wifi cards
|
38
|
+
@timeout = args[:timeout] || 1
|
39
|
+
@filter = args[:filter] || args[:bpf]
|
40
|
+
setup_params(args)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Used by new().
|
44
|
+
def setup_params(args={})
|
45
|
+
filter = args[:filter] || args[:bpf] || @filter
|
46
|
+
start = args[:start] || false
|
47
|
+
capture if start
|
48
|
+
bpf(:filter=>filter) if filter
|
49
|
+
end
|
50
|
+
|
51
|
+
# capture() initializes the @stream varaible. Valid arguments are:
|
52
|
+
#
|
53
|
+
# :filter
|
54
|
+
# Provide a bpf filter to enable for the capture. For example, 'ip and not tcp'
|
55
|
+
# :start
|
56
|
+
# When true, start capturing packets to the @stream variable. Defaults to true
|
57
|
+
def capture(args={})
|
58
|
+
if Process.euid.zero?
|
59
|
+
filter = args[:filter] || args[:bpf] || @filter
|
60
|
+
start = args[:start] || true
|
61
|
+
if start
|
62
|
+
begin
|
63
|
+
@stream = Pcap.open_live(@iface,@snaplen,@promisc,@timeout)
|
64
|
+
rescue RuntimeError
|
65
|
+
$stderr.print "Are you sure you're root? Error: "
|
66
|
+
raise
|
67
|
+
end
|
68
|
+
bpf(:filter=>filter) if filter
|
69
|
+
else
|
70
|
+
@stream = []
|
71
|
+
end
|
72
|
+
@stream
|
73
|
+
else
|
74
|
+
raise RuntimeError,"Not root, so can't capture packets. Error: "
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# start() is equivalent to capture().
|
79
|
+
def start(args={})
|
80
|
+
capture(args)
|
81
|
+
end
|
82
|
+
|
83
|
+
# clear() clears the @stream and @array variables, essentially starting the
|
84
|
+
# capture session over. Valid arguments are:
|
85
|
+
#
|
86
|
+
# :array
|
87
|
+
# If true, the @array is cleared.
|
88
|
+
# :stream
|
89
|
+
# If true, the @stream is cleared.
|
90
|
+
def clear(args={})
|
91
|
+
array = args[:array] || true
|
92
|
+
stream = args[:stream] || true
|
93
|
+
@array = [] if array
|
94
|
+
@stream = [] if stream
|
95
|
+
end
|
96
|
+
|
97
|
+
# bpf() sets a bpf filter on a capture session. Valid arugments are:
|
98
|
+
#
|
99
|
+
# :filter
|
100
|
+
# Provide a bpf filter to enable for the capture. For example, 'ip and not tcp'
|
101
|
+
def bpf(args={})
|
102
|
+
filter = args[:filter] || args[:bpf] || @filter
|
103
|
+
capture if @stream.class == Array
|
104
|
+
@stream.setfilter(filter) if filter
|
105
|
+
@filter = filter
|
106
|
+
end
|
107
|
+
|
108
|
+
alias :filter :bpf
|
109
|
+
|
110
|
+
# wire_to_array() saves a packet stream as an array of binary strings. From here,
|
111
|
+
# packets may accessed by other functions. Note that the wire_to_array empties
|
112
|
+
# the stream, so multiple calls will append new packets to @array.
|
113
|
+
# Valid arguments are:
|
114
|
+
#
|
115
|
+
# :filter
|
116
|
+
# Provide a bpf filter to apply to packets moving from @stream to @array.
|
117
|
+
def wire_to_array(args={})
|
118
|
+
filter = args[:filter] || args[:bpf] || @filter
|
119
|
+
bpf(:filter=>filter) if filter
|
120
|
+
|
121
|
+
while this_pkt = @stream.next
|
122
|
+
@array << this_pkt
|
123
|
+
end
|
124
|
+
@array.size
|
125
|
+
end
|
126
|
+
|
127
|
+
# next() exposes the Stream object's next method to the outside world.
|
128
|
+
def next
|
129
|
+
return @stream.next
|
130
|
+
end
|
131
|
+
|
132
|
+
# w2a() is a equivalent to wire_to_array()
|
133
|
+
def w2a(args={})
|
134
|
+
wire_to_array(args)
|
135
|
+
end
|
136
|
+
|
137
|
+
# save() is a equivalent to wire_to_array()
|
138
|
+
def save(args={})
|
139
|
+
wire_to_array(args)
|
140
|
+
end
|
141
|
+
|
142
|
+
# show_live() is a method to capture packets and display peek() data to stdout. Valid arguments are:
|
143
|
+
#
|
144
|
+
# :filter
|
145
|
+
# Provide a bpf filter to captured packets.
|
146
|
+
# :save
|
147
|
+
# Save the capture in @array
|
148
|
+
# :verbose
|
149
|
+
# TODO: Not implemented yet; do more than just peek() at the packets.
|
150
|
+
# :quiet
|
151
|
+
# TODO: Not implemented yet; do less than peek() at the packets.
|
152
|
+
def show_live(args={})
|
153
|
+
filter = args[:filter] || args[:bpf] || @filter
|
154
|
+
save = args[:save]
|
155
|
+
verbose = args[:verbose] || args[:v] || false
|
156
|
+
quiet = args[:quiet] || args[:q] || false # Setting q and v doesn't make a lot of sense but hey.
|
157
|
+
|
158
|
+
# Ensure the capture's started.
|
159
|
+
if @stream.class == Array
|
160
|
+
capture
|
161
|
+
end
|
162
|
+
|
163
|
+
@stream.setfilter(filter) if filter
|
164
|
+
while true
|
165
|
+
@stream.each do |pkt|
|
166
|
+
puts Packet.parse(pkt).peek
|
167
|
+
@array << pkt if args[:save]
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
end
|
173
173
|
end
|