pio 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CONTRIBUTING.md +46 -12
- data/README.md +131 -116
- data/Rakefile +7 -92
- data/examples/arp_new.rb +16 -0
- data/examples/arp_read.rb +4 -0
- data/examples/dhcp_new.rb +30 -0
- data/examples/dhcp_read.rb +4 -0
- data/examples/icmp_new.rb +21 -0
- data/examples/icmp_read.rb +4 -0
- data/examples/lldp_new.rb +4 -0
- data/examples/lldp_read.rb +4 -0
- data/lib/pio.rb +6 -12
- data/lib/pio/arp.rb +7 -19
- data/lib/pio/arp/frame.rb +8 -12
- data/lib/pio/arp/message.rb +12 -25
- data/lib/pio/arp/reply.rb +30 -30
- data/lib/pio/arp/request.rb +30 -29
- data/lib/pio/dhcp.rb +58 -0
- data/lib/pio/dhcp/ack.rb +12 -0
- data/lib/pio/dhcp/boot_reply.rb +16 -0
- data/lib/pio/dhcp/boot_reply_options.rb +75 -0
- data/lib/pio/dhcp/boot_request.rb +16 -0
- data/lib/pio/dhcp/boot_request_options.rb +69 -0
- data/lib/pio/dhcp/common_options.rb +71 -0
- data/lib/pio/dhcp/csum_util.rb +83 -0
- data/lib/pio/dhcp/dhcp_field.rb +48 -0
- data/lib/pio/dhcp/dhcp_tlv_options.rb +84 -0
- data/lib/pio/dhcp/discover.rb +12 -0
- data/lib/pio/dhcp/field_util.rb +102 -0
- data/lib/pio/dhcp/frame.rb +95 -0
- data/lib/pio/dhcp/message.rb +79 -0
- data/lib/pio/dhcp/offer.rb +12 -0
- data/lib/pio/dhcp/optional_tlv.rb +74 -0
- data/lib/pio/dhcp/request.rb +12 -0
- data/lib/pio/dhcp/type/dhcp_client_id.rb +21 -0
- data/lib/pio/dhcp/type/dhcp_param_list.rb +22 -0
- data/lib/pio/dhcp/type/dhcp_string.rb +21 -0
- data/lib/pio/icmp.rb +7 -18
- data/lib/pio/icmp/frame.rb +38 -40
- data/lib/pio/icmp/message.rb +10 -61
- data/lib/pio/icmp/options.rb +25 -0
- data/lib/pio/icmp/reply.rb +34 -7
- data/lib/pio/icmp/request.rb +43 -7
- data/lib/pio/ipv4_address.rb +5 -8
- data/lib/pio/lldp.rb +22 -62
- data/lib/pio/lldp/chassis_id_tlv.rb +7 -13
- data/lib/pio/lldp/end_of_lldpdu_value.rb +3 -9
- data/lib/pio/lldp/frame.rb +6 -12
- data/lib/pio/lldp/management_address_value.rb +4 -10
- data/lib/pio/lldp/optional_tlv.rb +5 -10
- data/lib/pio/lldp/options.rb +37 -0
- data/lib/pio/lldp/organizationally_specific_value.rb +2 -8
- data/lib/pio/lldp/port_description_value.rb +2 -8
- data/lib/pio/lldp/port_id_tlv.rb +6 -12
- data/lib/pio/lldp/system_capabilities_value.rb +2 -8
- data/lib/pio/lldp/system_description_value.rb +2 -8
- data/lib/pio/lldp/system_name_value.rb +2 -8
- data/lib/pio/lldp/ttl_tlv.rb +5 -11
- data/lib/pio/mac.rb +4 -9
- data/lib/pio/message_type_selector.rb +22 -0
- data/lib/pio/options.rb +65 -0
- data/lib/pio/parse_error.rb +6 -0
- data/lib/pio/type/ethernet_header.rb +3 -2
- data/lib/pio/type/ip_address.rb +4 -9
- data/lib/pio/type/ipv4_header.rb +12 -17
- data/lib/pio/type/mac_address.rb +5 -10
- data/lib/pio/type/udp_header.rb +18 -0
- data/lib/pio/version.rb +3 -8
- data/pio.gemspec +12 -10
- data/spec/pio/arp/reply/options_spec.rb +145 -0
- data/spec/pio/arp/reply_spec.rb +77 -113
- data/spec/pio/arp/request/options_spec.rb +115 -0
- data/spec/pio/arp/request_spec.rb +74 -96
- data/spec/pio/arp_spec.rb +71 -105
- data/spec/pio/dhcp/ack_spec.rb +189 -0
- data/spec/pio/dhcp/discover_spec.rb +165 -0
- data/spec/pio/dhcp/offer_spec.rb +189 -0
- data/spec/pio/dhcp/request_spec.rb +173 -0
- data/spec/pio/dhcp_spec.rb +609 -0
- data/spec/pio/icmp/reply_spec.rb +102 -95
- data/spec/pio/icmp/request_spec.rb +86 -78
- data/spec/pio/icmp_spec.rb +153 -146
- data/spec/pio/ipv4_address_spec.rb +2 -7
- data/spec/pio/lldp/options_spec.rb +188 -0
- data/spec/pio/lldp_spec.rb +181 -208
- data/spec/pio/mac_spec.rb +3 -8
- data/spec/spec_helper.rb +4 -10
- metadata +69 -17
- data/.gitignore +0 -20
- data/.rspec +0 -3
- data/.rubocop.yml +0 -1
- data/.travis.yml +0 -13
- data/Gemfile +0 -37
- data/Guardfile +0 -24
- data/lib/pio/message_util.rb +0 -19
- data/lib/pio/type/config.reek +0 -4
- data/lib/pio/util.rb +0 -21
- data/pio.org +0 -668
- data/pio.org_archive +0 -943
- data/rubocop-todo.yml +0 -9
@@ -1,5 +1,5 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
3
|
require 'bindata'
|
4
4
|
|
5
5
|
module Pio
|
@@ -8,12 +8,12 @@ module Pio
|
|
8
8
|
class ChassisIdTlv < BinData::Primitive
|
9
9
|
endian :big
|
10
10
|
|
11
|
-
bit7 :tlv_type, :
|
11
|
+
bit7 :tlv_type, value: 1
|
12
12
|
bit9(:tlv_info_length,
|
13
|
-
:
|
14
|
-
uint8 :subtype, :
|
13
|
+
value: -> { subtype.num_bytes + chassis_id.length })
|
14
|
+
uint8 :subtype, initial_value: 7
|
15
15
|
string(:chassis_id,
|
16
|
-
:
|
16
|
+
read_length: -> { tlv_info_length - subtype.num_bytes })
|
17
17
|
|
18
18
|
def get
|
19
19
|
tmp_chassis_id = chassis_id
|
@@ -40,15 +40,9 @@ module Pio
|
|
40
40
|
|
41
41
|
def mac_address
|
42
42
|
chassis_id.unpack('C6').map do |each|
|
43
|
-
|
43
|
+
format '%02x', each
|
44
44
|
end.join('').hex
|
45
45
|
end
|
46
46
|
end
|
47
47
|
end
|
48
48
|
end
|
49
|
-
|
50
|
-
### Local variables:
|
51
|
-
### mode: Ruby
|
52
|
-
### coding: utf-8-unix
|
53
|
-
### indent-tabs-mode: nil
|
54
|
-
### End:
|
@@ -1,5 +1,5 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
3
|
require 'bindata'
|
4
4
|
|
5
5
|
module Pio
|
@@ -8,13 +8,7 @@ module Pio
|
|
8
8
|
class EndOfLldpduValue < BinData::Record
|
9
9
|
endian :big
|
10
10
|
|
11
|
-
stringz :tlv_info_string, :
|
11
|
+
stringz :tlv_info_string, length: 0, value: ''
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
15
|
-
|
16
|
-
### Local variables:
|
17
|
-
### mode: Ruby
|
18
|
-
### coding: utf-8-unix
|
19
|
-
### indent-tabs-mode: nil
|
20
|
-
### End:
|
data/lib/pio/lldp/frame.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
3
|
require 'bindata'
|
4
4
|
|
5
5
|
require 'pio/lldp/chassis_id_tlv'
|
@@ -16,13 +16,13 @@ module Pio
|
|
16
16
|
|
17
17
|
endian :big
|
18
18
|
|
19
|
-
ethernet_header :
|
19
|
+
ethernet_header ether_type: 0x88cc
|
20
20
|
chassis_id_tlv :chassis_id
|
21
21
|
port_id_tlv :port_id
|
22
|
-
ttl_tlv :ttl, :
|
22
|
+
ttl_tlv :ttl, initial_value: 120
|
23
23
|
array(:optional_tlv,
|
24
|
-
:
|
25
|
-
:
|
24
|
+
type: :optional_tlv,
|
25
|
+
read_until: -> { element.end_of_lldpdu? })
|
26
26
|
|
27
27
|
def dpid
|
28
28
|
chassis_id.to_i
|
@@ -68,9 +68,3 @@ module Pio
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
end
|
71
|
-
|
72
|
-
### Local variables:
|
73
|
-
### mode: Ruby
|
74
|
-
### coding: utf-8-unix
|
75
|
-
### indent-tabs-mode: nil
|
76
|
-
### End:
|
@@ -1,5 +1,5 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
3
|
require 'bindata'
|
4
4
|
|
5
5
|
module Pio
|
@@ -10,17 +10,11 @@ module Pio
|
|
10
10
|
|
11
11
|
uint8 :string_length
|
12
12
|
uint8 :subtype
|
13
|
-
string :management_address, :
|
13
|
+
string :management_address, read_length: -> { string_length - 1 }
|
14
14
|
uint8 :interface_numbering_subtype
|
15
15
|
uint32 :interface_number
|
16
16
|
uint8 :oid_string_length
|
17
|
-
string :object_identifier, :
|
17
|
+
string :object_identifier, read_length: -> { oid_string_length }
|
18
18
|
end
|
19
19
|
end
|
20
20
|
end
|
21
|
-
|
22
|
-
### Local variables:
|
23
|
-
### mode: Ruby
|
24
|
-
### coding: utf-8-unix
|
25
|
-
### indent-tabs-mode: nil
|
26
|
-
### End:
|
@@ -1,4 +1,5 @@
|
|
1
|
-
#
|
1
|
+
# encoding: utf-8
|
2
|
+
|
2
3
|
require 'pio/lldp/port_description_value'
|
3
4
|
require 'pio/lldp/system_name_value'
|
4
5
|
require 'pio/lldp/system_description_value'
|
@@ -16,9 +17,9 @@ module Pio
|
|
16
17
|
bit7 :tlv_type
|
17
18
|
bit9 :tlv_info_length
|
18
19
|
choice :tlv_value,
|
19
|
-
:
|
20
|
-
:
|
21
|
-
:
|
20
|
+
read_length: :tlv_info_length,
|
21
|
+
onlyif: -> { !end_of_lldpdu? },
|
22
|
+
selection: :chooser do
|
22
23
|
end_of_lldpdu_value 0
|
23
24
|
port_description_value 4
|
24
25
|
system_name_value 5
|
@@ -58,9 +59,3 @@ module Pio
|
|
58
59
|
end
|
59
60
|
end
|
60
61
|
end
|
61
|
-
|
62
|
-
### Local variables:
|
63
|
-
### mode: Ruby
|
64
|
-
### coding: utf-8-unix
|
65
|
-
### indent-tabs-mode: nil
|
66
|
-
### End:
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'pio/options'
|
4
|
+
|
5
|
+
module Pio
|
6
|
+
class Lldp
|
7
|
+
# User options for creating an LLDP frame.
|
8
|
+
class Options < Pio::Options
|
9
|
+
mandatory_option :dpid
|
10
|
+
mandatory_option :port_number
|
11
|
+
option :destination_mac
|
12
|
+
option :source_mac
|
13
|
+
|
14
|
+
DEFAULT_DESTINATION_MAC = '01:80:c2:00:00:0e'.freeze
|
15
|
+
DEFAULT_SOURCE_MAC = '01:02:03:04:05:06'.freeze
|
16
|
+
|
17
|
+
def initialize(options)
|
18
|
+
validate options
|
19
|
+
@dpid = options[:dpid].freeze
|
20
|
+
@port_id = options[:port_number].freeze
|
21
|
+
@destination_mac =
|
22
|
+
Mac.new(options[:destination_mac] || DEFAULT_DESTINATION_MAC).freeze
|
23
|
+
@source_mac =
|
24
|
+
Mac.new(options[:source_mac] || DEFAULT_SOURCE_MAC).freeze
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_hash
|
28
|
+
{
|
29
|
+
chassis_id: @dpid,
|
30
|
+
port_id: @port_id,
|
31
|
+
destination_mac: @destination_mac,
|
32
|
+
source_mac: @source_mac
|
33
|
+
}.freeze
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
3
|
require 'bindata'
|
4
4
|
|
5
5
|
module Pio
|
@@ -14,9 +14,3 @@ module Pio
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
17
|
-
|
18
|
-
### Local variables:
|
19
|
-
### mode: Ruby
|
20
|
-
### coding: utf-8-unix
|
21
|
-
### indent-tabs-mode: nil
|
22
|
-
### End:
|
@@ -1,5 +1,5 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
3
|
require 'bindata'
|
4
4
|
|
5
5
|
module Pio
|
@@ -12,9 +12,3 @@ module Pio
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
15
|
-
|
16
|
-
### Local variables:
|
17
|
-
### mode: Ruby
|
18
|
-
### coding: utf-8-unix
|
19
|
-
### indent-tabs-mode: nil
|
20
|
-
### End:
|
data/lib/pio/lldp/port_id_tlv.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
3
|
require 'bindata'
|
4
4
|
|
5
5
|
module Pio
|
@@ -8,10 +8,10 @@ module Pio
|
|
8
8
|
class PortIdTlv < BinData::Primitive
|
9
9
|
endian :big
|
10
10
|
|
11
|
-
bit7 :tlv_type, :
|
12
|
-
bit9 :tlv_info_length, :
|
13
|
-
uint8 :subtype, :
|
14
|
-
string :port_id, :
|
11
|
+
bit7 :tlv_type, value: 2
|
12
|
+
bit9 :tlv_info_length, initial_value: -> { port_id.num_bytes + 1 }
|
13
|
+
uint8 :subtype, initial_value: 7
|
14
|
+
string :port_id, read_length: -> { tlv_info_length - 1 }
|
15
15
|
|
16
16
|
def get
|
17
17
|
tmp_id = port_id
|
@@ -33,9 +33,3 @@ module Pio
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
end
|
36
|
-
|
37
|
-
### Local variables:
|
38
|
-
### mode: Ruby
|
39
|
-
### coding: utf-8-unix
|
40
|
-
### indent-tabs-mode: nil
|
41
|
-
### End:
|
@@ -1,5 +1,5 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
3
|
require 'bindata'
|
4
4
|
|
5
5
|
module Pio
|
@@ -13,9 +13,3 @@ module Pio
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
16
|
-
|
17
|
-
### Local variables:
|
18
|
-
### mode: Ruby
|
19
|
-
### coding: utf-8-unix
|
20
|
-
### indent-tabs-mode: nil
|
21
|
-
### End:
|
@@ -1,5 +1,5 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
3
|
require 'bindata'
|
4
4
|
|
5
5
|
module Pio
|
@@ -12,9 +12,3 @@ module Pio
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
15
|
-
|
16
|
-
### Local variables:
|
17
|
-
### mode: Ruby
|
18
|
-
### coding: utf-8-unix
|
19
|
-
### indent-tabs-mode: nil
|
20
|
-
### End:
|
@@ -1,5 +1,5 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
3
|
require 'bindata'
|
4
4
|
|
5
5
|
module Pio
|
@@ -12,9 +12,3 @@ module Pio
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
15
|
-
|
16
|
-
### Local variables:
|
17
|
-
### mode: Ruby
|
18
|
-
### coding: utf-8-unix
|
19
|
-
### indent-tabs-mode: nil
|
20
|
-
### End:
|
data/lib/pio/lldp/ttl_tlv.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
3
|
require 'bindata'
|
4
4
|
|
5
5
|
module Pio
|
@@ -8,9 +8,9 @@ module Pio
|
|
8
8
|
class TtlTlv < BinData::Primitive
|
9
9
|
endian :big
|
10
10
|
|
11
|
-
bit7 :tlv_type, :
|
12
|
-
bit9 :tlv_info_length, :
|
13
|
-
string :ttl, :
|
11
|
+
bit7 :tlv_type, value: 3
|
12
|
+
bit9 :tlv_info_length, value: 2
|
13
|
+
string :ttl, read_length: :tlv_info_length
|
14
14
|
|
15
15
|
def get
|
16
16
|
BinData::Int16be.read(ttl)
|
@@ -22,9 +22,3 @@ module Pio
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
25
|
-
|
26
|
-
### Local variables:
|
27
|
-
### mode: Ruby
|
28
|
-
### coding: utf-8-unix
|
29
|
-
### indent-tabs-mode: nil
|
30
|
-
### End:
|
data/lib/pio/mac.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
#
|
1
|
+
# encoding: utf-8
|
2
|
+
|
2
3
|
require 'forwardable'
|
3
4
|
|
4
5
|
module Pio
|
@@ -60,7 +61,7 @@ module Pio
|
|
60
61
|
# @return [String]
|
61
62
|
#
|
62
63
|
def to_s
|
63
|
-
|
64
|
+
format('%012x', @value).unpack('a2' * 6).join(':')
|
64
65
|
end
|
65
66
|
|
66
67
|
#
|
@@ -191,7 +192,7 @@ module Pio
|
|
191
192
|
# @return [String]
|
192
193
|
#
|
193
194
|
def inspect
|
194
|
-
%
|
195
|
+
%(#<#{self.class}:#{__id__} "#{self}">)
|
195
196
|
end
|
196
197
|
|
197
198
|
# @!endgroup
|
@@ -212,9 +213,3 @@ module Pio
|
|
212
213
|
end
|
213
214
|
end
|
214
215
|
end
|
215
|
-
|
216
|
-
### Local variables:
|
217
|
-
### mode: Ruby
|
218
|
-
### coding: utf-8-unix
|
219
|
-
### indent-tabs-mode: nil
|
220
|
-
### End:
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'English'
|
4
|
+
|
5
|
+
module Pio
|
6
|
+
# Macros for defining message types.
|
7
|
+
module MessageTypeSelector
|
8
|
+
def message_type(options)
|
9
|
+
const_set(:MESSAGE_TYPE, options)
|
10
|
+
end
|
11
|
+
|
12
|
+
def read(raw_data)
|
13
|
+
begin
|
14
|
+
frame = const_get(:Frame).read(raw_data)
|
15
|
+
rescue
|
16
|
+
raise Pio::ParseError, $ERROR_INFO.message
|
17
|
+
end
|
18
|
+
|
19
|
+
const_get(:MESSAGE_TYPE)[frame.message_type].create_from frame
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/pio/options.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Pio
|
4
|
+
# User options utility.
|
5
|
+
class Options
|
6
|
+
def self.mandatory_option(name)
|
7
|
+
unless const_defined?(:MANDATORY_OPTIONS)
|
8
|
+
const_set(:MANDATORY_OPTIONS, [])
|
9
|
+
end
|
10
|
+
const_get(:MANDATORY_OPTIONS) << name
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.option(name)
|
14
|
+
const_set(:OPTIONS, []) unless const_defined?(:OPTIONS)
|
15
|
+
const_get(:OPTIONS) << name
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def validate(user_options)
|
21
|
+
check_unknown user_options
|
22
|
+
check_mandatory user_options
|
23
|
+
end
|
24
|
+
|
25
|
+
def mandatory_options
|
26
|
+
klass = self.class
|
27
|
+
if klass.const_defined?(:MANDATORY_OPTIONS)
|
28
|
+
klass.const_get(:MANDATORY_OPTIONS)
|
29
|
+
else
|
30
|
+
[]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def options
|
35
|
+
klass = self.class
|
36
|
+
if klass.const_defined?(:OPTIONS)
|
37
|
+
klass.const_get(:OPTIONS)
|
38
|
+
else
|
39
|
+
[]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def check_unknown(user_options)
|
44
|
+
valid_options = mandatory_options + options
|
45
|
+
user_options.keys.each do |each|
|
46
|
+
fail "Unknown option: #{each}." unless valid_options.include?(each)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def check_mandatory(user_options)
|
51
|
+
self.class.const_get(:MANDATORY_OPTIONS).each do |each|
|
52
|
+
check_existence(user_options, each)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def check_existence(user_options, key)
|
57
|
+
value = user_options.fetch(key) do |missing_key|
|
58
|
+
fail ArgumentError, "The #{missing_key} option should be passed."
|
59
|
+
end
|
60
|
+
unless value
|
61
|
+
fail(ArgumentError, "The #{key} option shouldn't be #{value.inspect}.")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|