DIY-pcap 0.4.1 → 0.4.3
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/.gitignore +4 -4
- data/DIY-pcap.gemspec +17 -17
- data/Gemfile +3 -3
- data/Rakefile +1 -1
- data/lib/DIY-pcap.rb +2 -2
- data/lib/diy/command.rb +7 -1
- data/lib/diy/controller.rb +10 -15
- data/lib/diy/live.rb +9 -2
- data/lib/diy/parser/mu/pcap/ethernet.rb +148 -148
- data/lib/diy/parser/mu/pcap/header.rb +75 -75
- data/lib/diy/parser/mu/pcap/io_pair.rb +67 -67
- data/lib/diy/parser/mu/pcap/io_wrapper.rb +76 -76
- data/lib/diy/parser/mu/pcap/ip.rb +61 -61
- data/lib/diy/parser/mu/pcap/ipv4.rb +257 -257
- data/lib/diy/parser/mu/pcap/ipv6.rb +148 -148
- data/lib/diy/parser/mu/pcap/packet.rb +104 -104
- data/lib/diy/parser/mu/pcap/pkthdr.rb +155 -155
- data/lib/diy/parser/mu/pcap/reader.rb +61 -61
- data/lib/diy/parser/mu/pcap/reader/http_family.rb +170 -170
- data/lib/diy/parser/mu/pcap/sctp.rb +367 -367
- data/lib/diy/parser/mu/pcap/sctp/chunk.rb +123 -123
- data/lib/diy/parser/mu/pcap/sctp/chunk/data.rb +134 -134
- data/lib/diy/parser/mu/pcap/sctp/chunk/init.rb +100 -100
- data/lib/diy/parser/mu/pcap/sctp/chunk/init_ack.rb +68 -68
- data/lib/diy/parser/mu/pcap/sctp/parameter.rb +110 -110
- data/lib/diy/parser/mu/pcap/sctp/parameter/ip_address.rb +48 -48
- data/lib/diy/parser/mu/pcap/stream_packetizer.rb +72 -72
- data/lib/diy/parser/mu/pcap/tcp.rb +505 -505
- data/lib/diy/parser/mu/pcap/udp.rb +69 -69
- data/lib/diy/parser/mu/scenario/pcap.rb +172 -172
- data/lib/diy/parser/mu/scenario/pcap/fields.rb +50 -50
- data/lib/diy/parser/mu/scenario/pcap/rtp.rb +71 -71
- data/lib/diy/parser/pcap.rb +109 -109
- data/lib/diy/version.rb +1 -1
- metadata +7 -9
data/.gitignore
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
*.gem
|
2
|
-
.bundle
|
3
|
-
Gemfile.lock
|
4
|
-
pkg/*
|
1
|
+
*.gem
|
2
|
+
.bundle
|
3
|
+
Gemfile.lock
|
4
|
+
pkg/*
|
5
5
|
*.txt
|
data/DIY-pcap.gemspec
CHANGED
@@ -1,19 +1,19 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
$:.push File.expand_path("../lib", __FILE__)
|
3
|
-
require "diy/version"
|
4
|
-
|
5
|
-
Gem::Specification.new do |s|
|
6
|
-
s.name = "DIY-pcap"
|
7
|
-
s.version = DIY::PCAP::VERSION
|
8
|
-
s.authors = ["yafei Lee"]
|
9
|
-
s.email = ["lyfi2003@gmail.com"]
|
10
|
-
s.homepage = ""
|
11
|
-
s.summary = %q{DIY pcap send and recv}
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "diy/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "DIY-pcap"
|
7
|
+
s.version = DIY::PCAP::VERSION
|
8
|
+
s.authors = ["yafei Lee"]
|
9
|
+
s.email = ["lyfi2003@gmail.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{DIY pcap send and recv}
|
12
12
|
s.description = %q{DIY pcap send and recv}
|
13
|
-
|
14
|
-
s.files = `git ls-files`.split("\n")
|
15
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
17
|
s.require_paths = ["lib"]
|
18
|
-
s.add_dependency "ffi-pcap", ">=0.2.0"
|
19
|
-
end
|
18
|
+
s.add_dependency "ffi-pcap", ">=0.2.0"
|
19
|
+
end
|
data/Gemfile
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
source "http://ruby.taobao.org"
|
2
|
-
|
3
|
-
# Specify your gem's dependencies in DIY-pcap.gemspec
|
1
|
+
source "http://ruby.taobao.org"
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in DIY-pcap.gemspec
|
4
4
|
gem "ffi-pcap", ">=0.2.0"
|
data/Rakefile
CHANGED
@@ -1 +1 @@
|
|
1
|
-
require 'bundler/gem_tasks'
|
1
|
+
require 'bundler/gem_tasks'
|
data/lib/DIY-pcap.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
require "diy/version"
|
2
|
-
require 'diy/pcap'
|
1
|
+
require "diy/version"
|
2
|
+
require 'diy/pcap'
|
3
3
|
require 'diy/dig'
|
data/lib/diy/command.rb
CHANGED
@@ -12,6 +12,7 @@ end
|
|
12
12
|
|
13
13
|
options = {
|
14
14
|
:ip => "0.0.0.0:#{$_PORT}",
|
15
|
+
:promisc => true,
|
15
16
|
}
|
16
17
|
|
17
18
|
OptionParser.new do |opts|
|
@@ -34,6 +35,11 @@ OptionParser.new do |opts|
|
|
34
35
|
exit 0
|
35
36
|
end
|
36
37
|
|
38
|
+
opts.on_tail("-o", "--non-promious", "Disable device's promiscuous mode", "default is enabled") do
|
39
|
+
DIY::Logger.info "Device's promiscuous mode is DISABLED"
|
40
|
+
options[:promisc] = false
|
41
|
+
end
|
42
|
+
|
37
43
|
opts.on_tail("--timer","Use TimerIdConv module instead of DRb's default idconv") do
|
38
44
|
options[:timer] = true
|
39
45
|
end
|
@@ -70,7 +76,7 @@ else
|
|
70
76
|
require 'diy/device_finder'
|
71
77
|
device_name = DIY::DeviceFinder.smart_select
|
72
78
|
end
|
73
|
-
device = DIY::Live.new(device_name)
|
79
|
+
device = DIY::Live.new(device_name, :promisc=> options[:promisc])
|
74
80
|
worker = DIY::Worker.new(device)
|
75
81
|
worker_keeper = DIY::WorkerKeeper.new(worker, uri)
|
76
82
|
if options[:timer]
|
data/lib/diy/controller.rb
CHANGED
@@ -124,7 +124,6 @@ module DIY
|
|
124
124
|
end
|
125
125
|
|
126
126
|
def client_send(client, pkts)
|
127
|
-
#~ pkt_contents = pkts.collect { |pkt| pkt.content }
|
128
127
|
begin
|
129
128
|
client.inject(pkts)
|
130
129
|
rescue FFI::PCap::LibError =>e
|
@@ -172,22 +171,18 @@ module DIY
|
|
172
171
|
end
|
173
172
|
|
174
173
|
def wait_recv_ok(pkts)
|
175
|
-
|
174
|
+
@timeout ||= 10
|
175
|
+
tick = 0
|
176
|
+
until pkts.empty? do
|
176
177
|
now_size = pkts.size
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
end
|
184
|
-
|
185
|
-
def wait_until( timeout = 10, &block )
|
186
|
-
Timeout.timeout(timeout, DIY::HopePacketTimeoutError.new("hope packet wait timeout after #{timeout} seconds") ) do
|
187
|
-
loop do
|
188
|
-
break if block.call
|
189
|
-
sleep 0.01
|
178
|
+
raise @error_flag if @error_flag
|
179
|
+
tick += 0.01
|
180
|
+
sleep 0.01
|
181
|
+
if pkts.size < now_size
|
182
|
+
# clear tick time if at least one packet has passed the judgement of stratgies.
|
183
|
+
tick = 0
|
190
184
|
end
|
185
|
+
raise DIY::HopePacketTimeoutError.new("hope packet wait timeout after #{@timeout} seconds") if !pkts.empty? && tick >= @timeout
|
191
186
|
end
|
192
187
|
end
|
193
188
|
|
data/lib/diy/live.rb
CHANGED
@@ -4,9 +4,12 @@ require 'diy/ext/capture_wrapper'
|
|
4
4
|
|
5
5
|
module DIY
|
6
6
|
class Live
|
7
|
-
def initialize(device_name)
|
7
|
+
def initialize(device_name, args = {})
|
8
8
|
DIY::Logger.info( "Initialize Live: #{device_name}" )
|
9
|
-
|
9
|
+
|
10
|
+
default = { :dev=>device_name, :handler => FFI::PCap::CopyHandler, :promisc => true, :timeout=>1 }
|
11
|
+
default = merge_arguments(default, args)
|
12
|
+
@live = FFI::PCap::Live.new(default)
|
10
13
|
DIY::Logger.info( "Listen on: #{net} " )
|
11
14
|
@running = false
|
12
15
|
@live.non_blocking= true
|
@@ -45,6 +48,10 @@ module DIY
|
|
45
48
|
@live.network + " / " + @live.netmask
|
46
49
|
end
|
47
50
|
|
51
|
+
def merge_arguments(default, new)
|
52
|
+
default.merge(new)
|
53
|
+
end
|
54
|
+
|
48
55
|
end # end of class Live
|
49
56
|
|
50
57
|
end
|
@@ -1,160 +1,160 @@
|
|
1
|
-
# http://www.mudynamics.com
|
2
|
-
# http://labs.mudynamics.com
|
3
|
-
# http://www.pcapr.net
|
4
|
-
|
5
|
-
module Mu
|
6
|
-
class Pcap
|
7
|
-
|
8
|
-
class Ethernet < Packet
|
9
|
-
attr_accessor :src, :dst, :type
|
10
|
-
|
11
|
-
ETHERTYPE_IP = 0x0800
|
12
|
-
ETHERTYPE_IP6 = 0x86dd
|
13
|
-
ETHERTYPE_ARP = 0x0806
|
14
|
-
ETHERTYPE_PPPOE_SESSION = 0x8864
|
15
|
-
ETHERTYPE_802_1Q = 0X8100
|
16
|
-
|
17
|
-
PPP_IP = 0x0021
|
18
|
-
PPP_IPV6 = 0x0057
|
19
|
-
|
20
|
-
def initialize src=nil, dst=nil, type=0
|
21
|
-
super()
|
22
|
-
@src = src
|
23
|
-
@dst = dst
|
1
|
+
# http://www.mudynamics.com
|
2
|
+
# http://labs.mudynamics.com
|
3
|
+
# http://www.pcapr.net
|
4
|
+
|
5
|
+
module Mu
|
6
|
+
class Pcap
|
7
|
+
|
8
|
+
class Ethernet < Packet
|
9
|
+
attr_accessor :src, :dst, :type
|
10
|
+
|
11
|
+
ETHERTYPE_IP = 0x0800
|
12
|
+
ETHERTYPE_IP6 = 0x86dd
|
13
|
+
ETHERTYPE_ARP = 0x0806
|
14
|
+
ETHERTYPE_PPPOE_SESSION = 0x8864
|
15
|
+
ETHERTYPE_802_1Q = 0X8100
|
16
|
+
|
17
|
+
PPP_IP = 0x0021
|
18
|
+
PPP_IPV6 = 0x0057
|
19
|
+
|
20
|
+
def initialize src=nil, dst=nil, type=0
|
21
|
+
super()
|
22
|
+
@src = src
|
23
|
+
@dst = dst
|
24
24
|
@type = type
|
25
|
-
@vlan = false
|
25
|
+
@vlan = false
|
26
26
|
end
|
27
27
|
attr_accessor :vlan
|
28
28
|
|
29
29
|
def vlan?
|
30
30
|
vlan
|
31
|
-
end
|
32
|
-
|
33
|
-
def flow_id
|
34
|
-
if not @payload or @payload.is_a? String
|
35
|
-
return [:ethernet, @src, @dst, @type]
|
36
|
-
else
|
37
|
-
return @payload.flow_id
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
FMT_MAC = "C6"
|
42
|
-
FMT_n = 'n'
|
43
|
-
MAC_TEMPLATE = '%02x:%02x:%02x:%02x:%02x:%02x'
|
44
|
-
def self.from_bytes bytes
|
45
|
-
if bytes.length < 14
|
46
|
-
raise ParseError, "Truncated Ethernet header: expected 14 bytes, got #{bytes.length} bytes"
|
47
|
-
end
|
48
|
-
|
49
|
-
dst = bytes.slice!(0,6).unpack FMT_MAC
|
50
|
-
dst = MAC_TEMPLATE % dst
|
51
|
-
src = bytes.slice!(0,6).unpack FMT_MAC
|
52
|
-
src = MAC_TEMPLATE % src
|
31
|
+
end
|
32
|
+
|
33
|
+
def flow_id
|
34
|
+
if not @payload or @payload.is_a? String
|
35
|
+
return [:ethernet, @src, @dst, @type]
|
36
|
+
else
|
37
|
+
return @payload.flow_id
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
FMT_MAC = "C6"
|
42
|
+
FMT_n = 'n'
|
43
|
+
MAC_TEMPLATE = '%02x:%02x:%02x:%02x:%02x:%02x'
|
44
|
+
def self.from_bytes bytes
|
45
|
+
if bytes.length < 14
|
46
|
+
raise ParseError, "Truncated Ethernet header: expected 14 bytes, got #{bytes.length} bytes"
|
47
|
+
end
|
48
|
+
|
49
|
+
dst = bytes.slice!(0,6).unpack FMT_MAC
|
50
|
+
dst = MAC_TEMPLATE % dst
|
51
|
+
src = bytes.slice!(0,6).unpack FMT_MAC
|
52
|
+
src = MAC_TEMPLATE % src
|
53
53
|
type = bytes.slice!(0,2).unpack(FMT_n)[0]
|
54
54
|
if type == ETHERTYPE_802_1Q
|
55
55
|
@vlan = true
|
56
56
|
else
|
57
57
|
@vlan = false
|
58
|
-
end
|
59
|
-
while (type == ETHERTYPE_802_1Q)
|
60
|
-
# Skip 4 bytes for 802.1q vlan tag field
|
61
|
-
bytes.slice!(0,2)
|
62
|
-
type = bytes.slice!(0,2).unpack(FMT_n)[0]
|
63
|
-
end
|
58
|
+
end
|
59
|
+
while (type == ETHERTYPE_802_1Q)
|
60
|
+
# Skip 4 bytes for 802.1q vlan tag field
|
61
|
+
bytes.slice!(0,2)
|
62
|
+
type = bytes.slice!(0,2).unpack(FMT_n)[0]
|
63
|
+
end
|
64
64
|
ethernet = Ethernet.new src, dst, type
|
65
|
-
ethernet.vlan = @vlan
|
66
|
-
ethernet.payload = bytes
|
67
|
-
ethernet.payload_raw = bytes
|
68
|
-
begin
|
69
|
-
case type
|
70
|
-
when ETHERTYPE_IP
|
71
|
-
ethernet.payload = IPv4.from_bytes bytes
|
72
|
-
when ETHERTYPE_IP6
|
73
|
-
ethernet.payload = IPv6.from_bytes bytes
|
74
|
-
when ETHERTYPE_PPPOE_SESSION
|
75
|
-
# Remove PPPoE/PPP session layer
|
76
|
-
ethernet.payload = bytes
|
77
|
-
ethernet.remove_pppoe!
|
78
|
-
else
|
79
|
-
ethernet.payload = bytes
|
80
|
-
end
|
81
|
-
rescue ParseError => e
|
82
|
-
Pcap.warning e
|
83
|
-
end
|
84
|
-
return ethernet
|
85
|
-
end
|
86
|
-
|
87
|
-
def ip?
|
88
|
-
return payload.is_a?(IP)
|
89
|
-
end
|
90
|
-
|
91
|
-
ADDR_TO_BYTES = {}
|
92
|
-
FMT_HEADER = 'a6a6n'
|
93
|
-
def write io
|
94
|
-
dst_mac = ADDR_TO_BYTES[@dst] ||= @dst.split(':').inject('') {|m, b| m << b.to_i(16).chr}
|
95
|
-
src_mac = ADDR_TO_BYTES[@src] ||= @src.split(':').inject('') {|m, b| m << b.to_i(16).chr}
|
96
|
-
bytes = [dst_mac, src_mac, @type].pack(FMT_HEADER)
|
97
|
-
io.write bytes
|
98
|
-
if @payload.is_a? String
|
99
|
-
io.write @payload
|
100
|
-
else
|
101
|
-
@payload.write io
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
# Remove the PPPoE and PPP headers. PPPoE is documented in RFC 2516.
|
106
|
-
def remove_pppoe!
|
107
|
-
bytes = self.payload_raw
|
108
|
-
|
109
|
-
# Remove PPPoE header
|
110
|
-
Pcap.assert bytes.length >= 6, 'Truncated PPPoE header: ' +
|
111
|
-
"expected at least 6 bytes, got #{bytes.length} bytes"
|
112
|
-
version_type, code, session_id, length = bytes.unpack 'CCnn'
|
113
|
-
version = version_type >> 4 & 0b1111
|
114
|
-
type = version_type & 0b1111
|
115
|
-
Pcap.assert version == 1, "Unknown PPPoE version: #{version}"
|
116
|
-
Pcap.assert type == 1, "Unknown PPPoE type: #{type}"
|
117
|
-
Pcap.assert code == 0, "Unknown PPPoE code: #{code}"
|
118
|
-
bytes = bytes[6..-1]
|
119
|
-
Pcap.assert bytes.length >= length, 'Truncated PPoE packet: ' +
|
120
|
-
"expected #{length} bytes, got #{bytes.length} bytes"
|
121
|
-
|
122
|
-
# Remove PPP header
|
123
|
-
Pcap.assert bytes.length >= 2, 'Truncated PPP packet: ' +
|
124
|
-
"expected at least bytes, got #{bytes.length} bytes"
|
125
|
-
protocol_id, = bytes.unpack 'n'
|
126
|
-
bytes = bytes[2..-1]
|
127
|
-
case protocol_id
|
128
|
-
when PPP_IP
|
129
|
-
self.payload = IPv4.from_bytes bytes
|
130
|
-
self.payload_raw = bytes
|
131
|
-
self.type = ETHERTYPE_IP
|
132
|
-
when PPP_IPV6
|
133
|
-
self.payload = IPv6.from_bytes bytes
|
134
|
-
self.payload_raw = bytes
|
135
|
-
self.type = ETHERTYPE_IP6
|
136
|
-
else
|
137
|
-
# Failed. Don't update payload or type.
|
138
|
-
raise ParseError, "Unknown PPP protocol: 0x#{'%04x' % protocol_id}"
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
def to_s
|
143
|
-
if @payload.is_a? String
|
144
|
-
payload = @payload.inspect
|
145
|
-
else
|
146
|
-
payload = @payload.to_s
|
147
|
-
end
|
148
|
-
return "ethernet(%s, %s, %d, %s)" % [@src, @dst, @type, payload]
|
149
|
-
end
|
150
|
-
|
151
|
-
def == other
|
152
|
-
return super &&
|
153
|
-
self.src == other.src &&
|
154
|
-
self.dst == other.dst &&
|
155
|
-
self.type == other.type
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
end
|
160
|
-
end
|
65
|
+
ethernet.vlan = @vlan
|
66
|
+
ethernet.payload = bytes
|
67
|
+
ethernet.payload_raw = bytes
|
68
|
+
begin
|
69
|
+
case type
|
70
|
+
when ETHERTYPE_IP
|
71
|
+
ethernet.payload = IPv4.from_bytes bytes
|
72
|
+
when ETHERTYPE_IP6
|
73
|
+
ethernet.payload = IPv6.from_bytes bytes
|
74
|
+
when ETHERTYPE_PPPOE_SESSION
|
75
|
+
# Remove PPPoE/PPP session layer
|
76
|
+
ethernet.payload = bytes
|
77
|
+
ethernet.remove_pppoe!
|
78
|
+
else
|
79
|
+
ethernet.payload = bytes
|
80
|
+
end
|
81
|
+
rescue ParseError => e
|
82
|
+
Pcap.warning e
|
83
|
+
end
|
84
|
+
return ethernet
|
85
|
+
end
|
86
|
+
|
87
|
+
def ip?
|
88
|
+
return payload.is_a?(IP)
|
89
|
+
end
|
90
|
+
|
91
|
+
ADDR_TO_BYTES = {}
|
92
|
+
FMT_HEADER = 'a6a6n'
|
93
|
+
def write io
|
94
|
+
dst_mac = ADDR_TO_BYTES[@dst] ||= @dst.split(':').inject('') {|m, b| m << b.to_i(16).chr}
|
95
|
+
src_mac = ADDR_TO_BYTES[@src] ||= @src.split(':').inject('') {|m, b| m << b.to_i(16).chr}
|
96
|
+
bytes = [dst_mac, src_mac, @type].pack(FMT_HEADER)
|
97
|
+
io.write bytes
|
98
|
+
if @payload.is_a? String
|
99
|
+
io.write @payload
|
100
|
+
else
|
101
|
+
@payload.write io
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# Remove the PPPoE and PPP headers. PPPoE is documented in RFC 2516.
|
106
|
+
def remove_pppoe!
|
107
|
+
bytes = self.payload_raw
|
108
|
+
|
109
|
+
# Remove PPPoE header
|
110
|
+
Pcap.assert bytes.length >= 6, 'Truncated PPPoE header: ' +
|
111
|
+
"expected at least 6 bytes, got #{bytes.length} bytes"
|
112
|
+
version_type, code, session_id, length = bytes.unpack 'CCnn'
|
113
|
+
version = version_type >> 4 & 0b1111
|
114
|
+
type = version_type & 0b1111
|
115
|
+
Pcap.assert version == 1, "Unknown PPPoE version: #{version}"
|
116
|
+
Pcap.assert type == 1, "Unknown PPPoE type: #{type}"
|
117
|
+
Pcap.assert code == 0, "Unknown PPPoE code: #{code}"
|
118
|
+
bytes = bytes[6..-1]
|
119
|
+
Pcap.assert bytes.length >= length, 'Truncated PPoE packet: ' +
|
120
|
+
"expected #{length} bytes, got #{bytes.length} bytes"
|
121
|
+
|
122
|
+
# Remove PPP header
|
123
|
+
Pcap.assert bytes.length >= 2, 'Truncated PPP packet: ' +
|
124
|
+
"expected at least bytes, got #{bytes.length} bytes"
|
125
|
+
protocol_id, = bytes.unpack 'n'
|
126
|
+
bytes = bytes[2..-1]
|
127
|
+
case protocol_id
|
128
|
+
when PPP_IP
|
129
|
+
self.payload = IPv4.from_bytes bytes
|
130
|
+
self.payload_raw = bytes
|
131
|
+
self.type = ETHERTYPE_IP
|
132
|
+
when PPP_IPV6
|
133
|
+
self.payload = IPv6.from_bytes bytes
|
134
|
+
self.payload_raw = bytes
|
135
|
+
self.type = ETHERTYPE_IP6
|
136
|
+
else
|
137
|
+
# Failed. Don't update payload or type.
|
138
|
+
raise ParseError, "Unknown PPP protocol: 0x#{'%04x' % protocol_id}"
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def to_s
|
143
|
+
if @payload.is_a? String
|
144
|
+
payload = @payload.inspect
|
145
|
+
else
|
146
|
+
payload = @payload.to_s
|
147
|
+
end
|
148
|
+
return "ethernet(%s, %s, %d, %s)" % [@src, @dst, @type, payload]
|
149
|
+
end
|
150
|
+
|
151
|
+
def == other
|
152
|
+
return super &&
|
153
|
+
self.src == other.src &&
|
154
|
+
self.dst == other.dst &&
|
155
|
+
self.type == other.type
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
160
|
+
end
|