DIY-pcap 0.4.1 → 0.4.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|