pio 0.6.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +56 -22
- data/examples/dhcp_new.rb +22 -18
- data/examples/features_new.rb +14 -0
- data/examples/features_read.rb +4 -0
- data/features/arp_read.feature +4 -4
- data/features/dhcp_read.feature +2 -2
- data/features/echo_read.feature +5 -0
- data/features/features_read.feature +10 -0
- data/features/hello_read.feature +5 -0
- data/features/icmp_read.feature +2 -2
- data/features/lldp_read.feature +4 -4
- data/features/{pcap → packet_data}/arp-storm.pcap +0 -0
- data/features/{pcap → packet_data}/arp.pcap +0 -0
- data/features/{pcap → packet_data}/dhcp.pcap +0 -0
- data/features/packet_data/echo.raw +0 -0
- data/features/packet_data/features_reply.raw +0 -0
- data/features/packet_data/features_request.raw +0 -0
- data/features/packet_data/hello.raw +0 -0
- data/features/{pcap → packet_data}/icmp.pcap +0 -0
- data/features/{pcap → packet_data}/lldp.detailed.pcap +0 -0
- data/features/{pcap → packet_data}/lldp.minimal.pcap +0 -0
- data/features/step_definitions/packet_data_steps.rb +32 -0
- data/features/step_definitions/pending_steps.rb +5 -0
- data/lib/pio.rb +1 -0
- data/lib/pio/arp.rb +1 -1
- data/lib/pio/arp/{frame.rb → format.rb} +2 -2
- data/lib/pio/arp/message.rb +2 -2
- data/lib/pio/dhcp/dhcp_field.rb +3 -3
- data/lib/pio/dhcp/frame.rb +6 -6
- data/lib/pio/dhcp/optional_tlv.rb +3 -3
- data/lib/pio/echo.rb +4 -11
- data/lib/pio/echo/format.rb +5 -5
- data/lib/pio/echo/message.rb +13 -4
- data/lib/pio/echo/reply.rb +29 -0
- data/lib/pio/echo/request.rb +29 -0
- data/lib/pio/features.rb +18 -0
- data/lib/pio/features/format.rb +18 -0
- data/lib/pio/features/message.rb +14 -0
- data/lib/pio/features/reply.rb +73 -0
- data/lib/pio/features/request.rb +63 -0
- data/lib/pio/hello.rb +40 -9
- data/lib/pio/icmp.rb +1 -1
- data/lib/pio/icmp/{frame.rb → format.rb} +2 -2
- data/lib/pio/icmp/message.rb +2 -2
- data/lib/pio/icmp/request.rb +30 -14
- data/lib/pio/message_type_selector.rb +4 -7
- data/lib/pio/type/ethernet_header.rb +0 -2
- data/lib/pio/type/ipv4_header.rb +0 -1
- data/lib/pio/type/open_flow.rb +34 -0
- data/lib/pio/type/udp_header.rb +0 -1
- data/lib/pio/version.rb +1 -1
- data/pio.gemspec +2 -2
- data/spec/pio/dhcp/ack_spec.rb +1 -1
- data/spec/pio/dhcp_spec.rb +2 -2
- data/spec/pio/echo/reply_spec.rb +69 -4
- data/spec/pio/echo/request_spec.rb +48 -10
- data/spec/pio/echo_spec.rb +8 -0
- data/spec/pio/features/reply_spec.rb +30 -0
- data/spec/pio/features/request_spec.rb +70 -0
- data/spec/pio/features_spec.rb +78 -0
- data/spec/pio/hello_spec.rb +35 -6
- data/spec/spec_helper.rb +3 -0
- metadata +70 -40
- data/features/step_definitions/pcap_steps.rb +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9f5e9be92c12989ecc7bfe94c76a5db47bb5304e
|
4
|
+
data.tar.gz: dc6414ddb0c09cc48489295b5d4c746cfda522e9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a5b3da4c83662a1d20002dde48e926c71becb41f22c8efc4151a7966dcc75566333c17cb9d6f14805741d521914bc98caf97c940c7add564a7fb676aec876ed9
|
7
|
+
data.tar.gz: 081cc576cb1481899bd8733462e914f7644ccd1e51138bece41ff93851f432c63c6c56f4872519d297366b9e8c1524d237d40eaeff06f3cd8ab27a92b4df1bac
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 0.7.0 (4/22/2014)
|
4
|
+
|
5
|
+
### New features
|
6
|
+
* Added new class `Pio::Features`, `Pio::Features::Request` and `Pio::Features::Reply`
|
7
|
+
|
8
|
+
### Changes
|
9
|
+
* Renamed `rake PCAP='foo.pcap' dump_pcap` => `rake PACKET_FILE='foo.pcap' dump`
|
10
|
+
|
11
|
+
|
3
12
|
## 0.6.0 (4/15/2014)
|
4
13
|
|
5
14
|
### New features
|
data/README.md
CHANGED
@@ -18,7 +18,8 @@ supports the following packet formats:
|
|
18
18
|
- DHCP
|
19
19
|
- OpenFlow 1.0
|
20
20
|
- Hello
|
21
|
-
- Echo
|
21
|
+
- Echo
|
22
|
+
- Features
|
22
23
|
- (…currently there are just a few formats supported but I'm sure this list will grow)
|
23
24
|
|
24
25
|
## Features Overview
|
@@ -132,33 +133,37 @@ Also you can use `Pio::Dhcp::Discover#new`,
|
|
132
133
|
|
133
134
|
require 'pio'
|
134
135
|
|
135
|
-
|
136
|
+
dhcp_client_mac_address = '24:db:ac:41:e5:5b'
|
137
|
+
|
138
|
+
dhcp_server_options =
|
139
|
+
{
|
140
|
+
source_mac: '00:26:82:eb:ea:d1',
|
141
|
+
destination_mac: '24:db:ac:41:e5:5b',
|
142
|
+
ip_source_address: '192.168.0.100',
|
143
|
+
ip_destination_address: '192.168.0.1'
|
144
|
+
}
|
145
|
+
|
146
|
+
# Client side
|
147
|
+
discover = Pio::Dhcp::Discover.new(source_mac: dhcp_client_mac_address)
|
136
148
|
discover.to_binary # => DHCP Discover frame in binary format
|
137
149
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
ip_source_address: '192.168.0.100',
|
142
|
-
ip_destination_address: '192.168.0.1',
|
143
|
-
transaction_id: discover.transaction_id
|
144
|
-
)
|
150
|
+
# Server side
|
151
|
+
offer = Pio::Dhcp::Offer.new(dhcp_server_options
|
152
|
+
.merge(transaction_id: discover.transaction_id))
|
145
153
|
offer.to_binary # => DHCP Offer frame in binary format
|
146
154
|
|
155
|
+
# Client side
|
147
156
|
request = Pio::Dhcp::Request.new(
|
148
|
-
source_mac:
|
149
|
-
server_identifier:
|
150
|
-
requested_ip_address:
|
157
|
+
source_mac: dhcp_client_mac_address,
|
158
|
+
server_identifier: dhcp_server_options[:ip_source_address],
|
159
|
+
requested_ip_address: dhcp_server_options[:ip_destination_address],
|
151
160
|
transaction_id: offer.transaction_id
|
152
161
|
)
|
153
162
|
request.to_binary # => DHCP Request frame in binary format
|
154
163
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
ip_source_address: '192.168.0.100',
|
159
|
-
ip_destination_address: '192.168.0.1',
|
160
|
-
transaction_id: request.transaction_id
|
161
|
-
)
|
164
|
+
# Server side
|
165
|
+
ack = Pio::Dhcp::Ack.new(dhcp_server_options
|
166
|
+
.merge(transaction_id: request.transaction_id))
|
162
167
|
ack.to_binary # => DHCP Ack frame in binary format
|
163
168
|
|
164
169
|
### Hello
|
@@ -179,10 +184,10 @@ below:
|
|
179
184
|
hello = Pio::Hello.new(transaction_id: 123)
|
180
185
|
hello.to_binary # => HELLO message in binary format.
|
181
186
|
|
182
|
-
|
187
|
+
### Echo
|
183
188
|
|
184
|
-
To parse an OpenFlow 1.0
|
185
|
-
and you can access each field of the parsed
|
189
|
+
To parse an OpenFlow 1.0 Echo message, use the API `Pio::Echo.read`
|
190
|
+
and you can access each field of the parsed Echo message.
|
186
191
|
|
187
192
|
require 'pio'
|
188
193
|
|
@@ -202,6 +207,35 @@ generate an Echo Request/Reply message like below:
|
|
202
207
|
reply = Pio::Echo::Reply.new(xid: request.xid)
|
203
208
|
reply.to_binary # => ECHO Reply message in binary format.
|
204
209
|
|
210
|
+
### Features
|
211
|
+
|
212
|
+
To parse an OpenFlow 1.0 Features message, use the API
|
213
|
+
`Pio::Features.read` and you can access each field of the parsed
|
214
|
+
Features message.
|
215
|
+
|
216
|
+
require 'pio'
|
217
|
+
|
218
|
+
features = Pio::Features.read(binary_data)
|
219
|
+
features.xid # => 123
|
220
|
+
|
221
|
+
Also you can use `Pio::Features::Request#new` or `Pio::Features::Reply#new` to
|
222
|
+
generate an Features Request/Reply message like below:
|
223
|
+
|
224
|
+
require 'pio'
|
225
|
+
|
226
|
+
request = Pio::Features::Request.new
|
227
|
+
request.to_binary # => Features Request message in binary format.
|
228
|
+
|
229
|
+
# The Features xid (transaction_id)
|
230
|
+
# should be same as that of the request.
|
231
|
+
reply = Pio::Features::Reply.new(xid: request.xid,
|
232
|
+
dpid: 0x123,
|
233
|
+
n_buffers: 0x100,
|
234
|
+
n_tables: 0xfe,
|
235
|
+
capabilities: 0xc7,
|
236
|
+
actions: 0xfff)
|
237
|
+
reply.to_binary # => Features Reply message in binary format.
|
238
|
+
|
205
239
|
## Installation
|
206
240
|
|
207
241
|
The simplest way to install Pio is to use [Bundler](http://gembundler.com/).
|
data/examples/dhcp_new.rb
CHANGED
@@ -1,30 +1,34 @@
|
|
1
1
|
require 'pio'
|
2
2
|
|
3
|
-
|
3
|
+
dhcp_client_mac_address = '24:db:ac:41:e5:5b'
|
4
|
+
|
5
|
+
dhcp_server_options =
|
6
|
+
{
|
7
|
+
source_mac: '00:26:82:eb:ea:d1',
|
8
|
+
destination_mac: '24:db:ac:41:e5:5b',
|
9
|
+
ip_source_address: '192.168.0.100',
|
10
|
+
ip_destination_address: '192.168.0.1'
|
11
|
+
}
|
12
|
+
|
13
|
+
# Client side
|
14
|
+
discover = Pio::Dhcp::Discover.new(source_mac: dhcp_client_mac_address)
|
4
15
|
discover.to_binary # => DHCP Discover frame in binary format
|
5
16
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
ip_source_address: '192.168.0.100',
|
10
|
-
ip_destination_address: '192.168.0.1',
|
11
|
-
transaction_id: discover.transaction_id
|
12
|
-
)
|
17
|
+
# Server side
|
18
|
+
offer = Pio::Dhcp::Offer.new(dhcp_server_options
|
19
|
+
.merge(transaction_id: discover.transaction_id))
|
13
20
|
offer.to_binary # => DHCP Offer frame in binary format
|
14
21
|
|
22
|
+
# Client side
|
15
23
|
request = Pio::Dhcp::Request.new(
|
16
|
-
source_mac:
|
17
|
-
server_identifier:
|
18
|
-
requested_ip_address:
|
24
|
+
source_mac: dhcp_client_mac_address,
|
25
|
+
server_identifier: dhcp_server_options[:ip_source_address],
|
26
|
+
requested_ip_address: dhcp_server_options[:ip_destination_address],
|
19
27
|
transaction_id: offer.transaction_id
|
20
28
|
)
|
21
29
|
request.to_binary # => DHCP Request frame in binary format
|
22
30
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
ip_source_address: '192.168.0.100',
|
27
|
-
ip_destination_address: '192.168.0.1',
|
28
|
-
transaction_id: request.transaction_id
|
29
|
-
)
|
31
|
+
# Server side
|
32
|
+
ack = Pio::Dhcp::Ack.new(dhcp_server_options
|
33
|
+
.merge(transaction_id: request.transaction_id))
|
30
34
|
ack.to_binary # => DHCP Ack frame in binary format
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'pio'
|
2
|
+
|
3
|
+
request = Pio::Features::Request.new
|
4
|
+
request.to_binary # => Features Request message in binary format.
|
5
|
+
|
6
|
+
# The Features xid (transaction_id)
|
7
|
+
# should be same as that of the request.
|
8
|
+
reply = Pio::Features::Reply.new(xid: request.xid,
|
9
|
+
dpid: 0x123,
|
10
|
+
n_buffers: 0x100,
|
11
|
+
n_tables: 0xfe,
|
12
|
+
capabilities: 0xc7,
|
13
|
+
actions: 0xfff)
|
14
|
+
reply.to_binary # => Features Reply message in binary format.
|
data/features/arp_read.feature
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
Feature: Pio::Arp.read
|
2
2
|
Scenario: arp.pcap
|
3
|
-
Given a
|
4
|
-
When I try to parse the
|
3
|
+
Given a packet data file "arp.pcap"
|
4
|
+
When I try to parse the file with "Arp" class
|
5
5
|
Then it should finish successfully
|
6
6
|
|
7
7
|
Scenario: arp-storm.pcap
|
8
|
-
Given a
|
9
|
-
When I try to parse the
|
8
|
+
Given a packet data file "arp-storm.pcap"
|
9
|
+
When I try to parse the file with "Arp" class
|
10
10
|
Then it should finish successfully
|
data/features/dhcp_read.feature
CHANGED
@@ -0,0 +1,10 @@
|
|
1
|
+
Feature: Pio::Features.read
|
2
|
+
Scenario: features_request.raw
|
3
|
+
Given a packet data file "features_request.raw"
|
4
|
+
When I try to parse the file with "Features" class
|
5
|
+
Then it should finish successfully
|
6
|
+
|
7
|
+
Scenario: features_reply.raw
|
8
|
+
Given a packet data file "features_reply.raw"
|
9
|
+
When I try to parse the file with "Features" class
|
10
|
+
Then it should finish successfully
|
data/features/icmp_read.feature
CHANGED
data/features/lldp_read.feature
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
Feature: Pio::Lldp.read
|
2
2
|
Scenario: lldp.minimal.pcap
|
3
|
-
Given a
|
4
|
-
When I try to parse the
|
3
|
+
Given a packet data file "lldp.minimal.pcap"
|
4
|
+
When I try to parse the file with "Lldp" class
|
5
5
|
Then it should finish successfully
|
6
6
|
|
7
7
|
Scenario: lldp.detailed.pcap
|
8
|
-
Given a
|
9
|
-
When I try to parse the
|
8
|
+
Given a packet data file "lldp.detailed.pcap"
|
9
|
+
When I try to parse the file with "Lldp" class
|
10
10
|
Then it should finish successfully
|
File without changes
|
File without changes
|
File without changes
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
Given(/^a packet data file "(.*?)"$/) do |name|
|
4
|
+
path = File.expand_path(File.join(File.dirname(__FILE__),
|
5
|
+
'..', 'packet_data', name))
|
6
|
+
case File.extname(name)
|
7
|
+
when '.raw'
|
8
|
+
@raw = path
|
9
|
+
when '.pcap'
|
10
|
+
@pcap = path
|
11
|
+
else
|
12
|
+
fail "Unsupported file extension: #{name}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
When(/^I try to parse the file with "(.*?)" class$/) do |parser|
|
17
|
+
parser_klass = Pio.const_get(parser)
|
18
|
+
if @raw
|
19
|
+
parser_klass.read IO.read(@raw)
|
20
|
+
elsif @pcap
|
21
|
+
File.open(@pcap) do |file|
|
22
|
+
pcap = Pio::Pcap::Frame.read(file)
|
23
|
+
pcap.records.each { |each| parser_klass.read each.data }
|
24
|
+
end
|
25
|
+
else
|
26
|
+
fail 'Packet data file is not specified.'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
Then(/^it should finish successfully$/) do
|
31
|
+
# Noop.
|
32
|
+
end
|
data/lib/pio.rb
CHANGED
data/lib/pio/arp.rb
CHANGED
data/lib/pio/arp/message.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
require 'forwardable'
|
4
|
-
require 'pio/arp/
|
4
|
+
require 'pio/arp/format'
|
5
5
|
|
6
6
|
module Pio
|
7
7
|
class Arp
|
@@ -33,7 +33,7 @@ module Pio
|
|
33
33
|
|
34
34
|
def initialize(user_options)
|
35
35
|
options = self.class.const_get(:Options).new(user_options.dup.freeze)
|
36
|
-
@frame = Arp::
|
36
|
+
@frame = Arp::Format.new(options.to_hash)
|
37
37
|
end
|
38
38
|
end
|
39
39
|
end
|
data/lib/pio/dhcp/dhcp_field.rb
CHANGED
@@ -40,9 +40,9 @@ module Pio
|
|
40
40
|
length: 128
|
41
41
|
uint32be :magic_cookie,
|
42
42
|
value: MAGIC_COOKIE
|
43
|
-
array
|
44
|
-
|
45
|
-
|
43
|
+
array :optional_tlvs,
|
44
|
+
type: :optional_tlv,
|
45
|
+
read_until: -> { element.end_of_dhcptlv? }
|
46
46
|
end
|
47
47
|
end
|
48
48
|
end
|
data/lib/pio/dhcp/frame.rb
CHANGED
@@ -26,12 +26,12 @@ module Pio
|
|
26
26
|
endian :big
|
27
27
|
|
28
28
|
ethernet_header ether_type: ETHER_TYPE_IP
|
29
|
-
ipv4_header
|
30
|
-
|
31
|
-
|
32
|
-
udp_header
|
33
|
-
|
34
|
-
dhcp_field
|
29
|
+
ipv4_header ip_protocol: IP_PROTOCOL_UDP,
|
30
|
+
ip_header_checksum: -> { ip_sum },
|
31
|
+
ip_total_length: -> { ip_len }
|
32
|
+
udp_header udp_length: -> { udp_len },
|
33
|
+
udp_checksum: -> { udp_sum }
|
34
|
+
dhcp_field :dhcp
|
35
35
|
|
36
36
|
def ip_sum
|
37
37
|
~((ip_csum & 0xffff) + (ip_csum >> 16)) & 0xffff
|
@@ -16,9 +16,9 @@ module Pio
|
|
16
16
|
bit8 :tlv_type
|
17
17
|
bit8 :tlv_info_length,
|
18
18
|
onlyif: -> { !(end_of_dhcpdu?) }
|
19
|
-
choice
|
20
|
-
|
21
|
-
|
19
|
+
choice :tlv_value,
|
20
|
+
onlyif: -> { !(end_of_dhcpdu?) },
|
21
|
+
selection: :chooser do
|
22
22
|
uint8 Dhcp::MESSAGE_TYPE_TLV
|
23
23
|
ip_address Dhcp::SERVER_IDENTIFIER_TLV
|
24
24
|
uint32be Dhcp::RENEWAL_TIME_VALUE_TLV
|