pio 0.3.0 → 0.4.0
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.
- 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
@@ -0,0 +1,102 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Pio
|
4
|
+
class Dhcp
|
5
|
+
# Dhcp Field Read Methods.
|
6
|
+
module FieldUtil
|
7
|
+
def message_type
|
8
|
+
get_tlv_field(53)
|
9
|
+
end
|
10
|
+
|
11
|
+
def server_identifier
|
12
|
+
get_tlv_field(54)
|
13
|
+
end
|
14
|
+
|
15
|
+
def client_identifier
|
16
|
+
get_tlv_field(61)
|
17
|
+
end
|
18
|
+
|
19
|
+
def renewal_time_value
|
20
|
+
get_tlv_field(58)
|
21
|
+
end
|
22
|
+
|
23
|
+
def rebinding_time_value
|
24
|
+
get_tlv_field(59)
|
25
|
+
end
|
26
|
+
|
27
|
+
def ip_address_lease_time
|
28
|
+
get_tlv_field(51)
|
29
|
+
end
|
30
|
+
|
31
|
+
def requested_ip_address
|
32
|
+
get_tlv_field(50)
|
33
|
+
end
|
34
|
+
|
35
|
+
def parameters_list
|
36
|
+
get_tlv_field(55)
|
37
|
+
end
|
38
|
+
|
39
|
+
def subnet_mask
|
40
|
+
get_tlv_field(1)
|
41
|
+
end
|
42
|
+
|
43
|
+
def hw_addr_type
|
44
|
+
dhcp.hw_addr_type
|
45
|
+
end
|
46
|
+
|
47
|
+
def hw_addr_len
|
48
|
+
dhcp.hw_addr_len
|
49
|
+
end
|
50
|
+
|
51
|
+
def hops
|
52
|
+
dhcp.hops
|
53
|
+
end
|
54
|
+
|
55
|
+
def transaction_id
|
56
|
+
dhcp.transaction_id
|
57
|
+
end
|
58
|
+
|
59
|
+
def seconds
|
60
|
+
dhcp.seconds
|
61
|
+
end
|
62
|
+
|
63
|
+
def bootp_flags
|
64
|
+
dhcp.bootp_flags
|
65
|
+
end
|
66
|
+
|
67
|
+
def client_ip_address
|
68
|
+
dhcp.client_ip_address
|
69
|
+
end
|
70
|
+
|
71
|
+
def your_ip_address
|
72
|
+
dhcp.your_ip_address
|
73
|
+
end
|
74
|
+
|
75
|
+
def next_server_ip_address
|
76
|
+
dhcp.next_server_ip_address
|
77
|
+
end
|
78
|
+
|
79
|
+
def relay_agent_ip_address
|
80
|
+
dhcp.relay_agent_ip_address
|
81
|
+
end
|
82
|
+
|
83
|
+
def client_mac_address
|
84
|
+
dhcp.client_mac_address
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def get_tlv(tlv_type)
|
90
|
+
tlv = dhcp.optional_tlvs.find do | each |
|
91
|
+
each['tlv_type'] == tlv_type
|
92
|
+
end
|
93
|
+
tlv['tlv_value'] if tlv
|
94
|
+
end
|
95
|
+
|
96
|
+
def get_tlv_field(tlv_type)
|
97
|
+
tlv = get_tlv(tlv_type)
|
98
|
+
tlv.snapshot if tlv
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'pio/type/ethernet_header'
|
4
|
+
require 'pio/type/ipv4_header'
|
5
|
+
require 'pio/type/udp_header'
|
6
|
+
require 'pio/dhcp/dhcp_field'
|
7
|
+
require 'pio/dhcp/field_util'
|
8
|
+
require 'pio/dhcp/csum_util'
|
9
|
+
|
10
|
+
module Pio
|
11
|
+
class Dhcp
|
12
|
+
# Dhcp frame parser.
|
13
|
+
class Frame < BinData::Record
|
14
|
+
extend Type::EthernetHeader
|
15
|
+
extend Type::IPv4Header
|
16
|
+
extend Type::UdpHeader
|
17
|
+
include FieldUtil
|
18
|
+
include CsumUtil
|
19
|
+
|
20
|
+
ETHER_TYPE_IP = 0x0800
|
21
|
+
IP_PROTOCOL_UDP = 17
|
22
|
+
IP_HEADER_LENGTH = 20
|
23
|
+
UDP_HEADER_LENGTH = 8
|
24
|
+
DHCP_OPTION_FIELD_LENGTH = 60
|
25
|
+
|
26
|
+
endian :big
|
27
|
+
|
28
|
+
ethernet_header ether_type: ETHER_TYPE_IP
|
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
|
+
|
36
|
+
def ip_sum
|
37
|
+
~((ip_csum & 0xffff) + (ip_csum >> 16)) & 0xffff
|
38
|
+
end
|
39
|
+
|
40
|
+
def udp_sum
|
41
|
+
~((udp_csum & 0xffff) + (udp_csum >> 16)) & 0xffff
|
42
|
+
end
|
43
|
+
|
44
|
+
def ip_len
|
45
|
+
IP_HEADER_LENGTH + udp_len
|
46
|
+
end
|
47
|
+
|
48
|
+
def udp_len
|
49
|
+
UDP_HEADER_LENGTH + dhcp_len
|
50
|
+
end
|
51
|
+
|
52
|
+
def to_binary
|
53
|
+
to_binary_s + trail_data
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def dhcp_len
|
59
|
+
dhcp.num_bytes + trail_data.bytesize
|
60
|
+
end
|
61
|
+
|
62
|
+
def dhcp_binary
|
63
|
+
dhcp.to_binary_s
|
64
|
+
end
|
65
|
+
|
66
|
+
def should_padding?
|
67
|
+
option_length < DHCP_OPTION_FIELD_LENGTH
|
68
|
+
end
|
69
|
+
|
70
|
+
def option_length
|
71
|
+
dhcp.optional_tlvs.num_bytes + 1
|
72
|
+
end
|
73
|
+
|
74
|
+
def trail_data
|
75
|
+
if should_padding?
|
76
|
+
end_of_pdu + padding
|
77
|
+
else
|
78
|
+
end_of_pdu
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def end_of_pdu
|
83
|
+
[0xff].pack('C*')
|
84
|
+
end
|
85
|
+
|
86
|
+
def padding
|
87
|
+
[0x00].pack('C*') * padding_length
|
88
|
+
end
|
89
|
+
|
90
|
+
def padding_length
|
91
|
+
DHCP_OPTION_FIELD_LENGTH - option_length
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'pio/dhcp/frame'
|
4
|
+
require 'forwardable'
|
5
|
+
|
6
|
+
module Pio
|
7
|
+
class Dhcp
|
8
|
+
# Base class of Dhcp Packet Generator and Parser.
|
9
|
+
class Message
|
10
|
+
extend Forwardable
|
11
|
+
|
12
|
+
def_delegators :@frame, :destination_mac
|
13
|
+
def_delegators :@frame, :source_mac
|
14
|
+
def_delegators :@frame, :ether_type
|
15
|
+
def_delegators :@frame, :ip_version
|
16
|
+
def_delegators :@frame, :ip_header_length
|
17
|
+
def_delegators :@frame, :ip_type_of_service
|
18
|
+
def_delegators :@frame, :ip_total_length
|
19
|
+
def_delegators :@frame, :ip_identifier
|
20
|
+
def_delegators :@frame, :ip_flag
|
21
|
+
def_delegators :@frame, :ip_fragment
|
22
|
+
def_delegators :@frame, :ip_ttl
|
23
|
+
def_delegators :@frame, :ip_protocol
|
24
|
+
def_delegators :@frame, :ip_header_checksum
|
25
|
+
def_delegators :@frame, :ip_source_address
|
26
|
+
def_delegators :@frame, :ip_destination_address
|
27
|
+
def_delegators :@frame, :udp_src_port
|
28
|
+
def_delegators :@frame, :udp_dst_port
|
29
|
+
def_delegators :@frame, :udp_length
|
30
|
+
def_delegators :@frame, :udp_checksum
|
31
|
+
def_delegators :@frame, :dhcp
|
32
|
+
def_delegators :@frame, :optioal_tlvs
|
33
|
+
def_delegators :@frame, :boot_message_type
|
34
|
+
def_delegators :@frame, :message_type
|
35
|
+
def_delegators :@frame, :hw_addr_type
|
36
|
+
def_delegators :@frame, :hw_addr_len
|
37
|
+
def_delegators :@frame, :hops
|
38
|
+
def_delegators :@frame, :transaction_id
|
39
|
+
def_delegators :@frame, :seconds
|
40
|
+
def_delegators :@frame, :bootp_flags
|
41
|
+
def_delegators :@frame, :client_ip_address
|
42
|
+
def_delegators :@frame, :your_ip_address
|
43
|
+
def_delegators :@frame, :next_server_ip_address
|
44
|
+
def_delegators :@frame, :relay_agent_ip_address
|
45
|
+
def_delegators :@frame, :client_mac_address
|
46
|
+
def_delegators :@frame, :server_host_name
|
47
|
+
def_delegators :@frame, :boot_file_name
|
48
|
+
def_delegators :@frame, :server_identifier
|
49
|
+
def_delegators :@frame, :renewal_time_value
|
50
|
+
def_delegators :@frame, :rebinding_time_value
|
51
|
+
def_delegators :@frame, :ip_address_lease_time
|
52
|
+
def_delegators :@frame, :subnet_mask
|
53
|
+
def_delegators :@frame, :client_identifier
|
54
|
+
def_delegators :@frame, :requested_ip_address
|
55
|
+
def_delegators :@frame, :parameters_list
|
56
|
+
def_delegators :@frame, :to_binary
|
57
|
+
|
58
|
+
def self.create_from(frame)
|
59
|
+
message = allocate
|
60
|
+
message.instance_variable_set :@frame, frame
|
61
|
+
message
|
62
|
+
end
|
63
|
+
|
64
|
+
def initialize(user_options)
|
65
|
+
type_merged_options = user_options.merge type: const_type
|
66
|
+
options = options_klass.new(type_merged_options)
|
67
|
+
@frame = Dhcp::Frame.new(options.to_hash)
|
68
|
+
end
|
69
|
+
|
70
|
+
def const_type
|
71
|
+
self.class::TYPE
|
72
|
+
end
|
73
|
+
|
74
|
+
def options_klass
|
75
|
+
self.class.const_get(:Options)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'pio/dhcp/type/dhcp_param_list'
|
4
|
+
require 'pio/dhcp/type/dhcp_client_id'
|
5
|
+
require 'pio/dhcp/type/dhcp_string'
|
6
|
+
require 'pio/type/ip_address'
|
7
|
+
|
8
|
+
module Pio
|
9
|
+
# Dhcp parser and generator.
|
10
|
+
class Dhcp
|
11
|
+
# DHCP Optional TLV
|
12
|
+
class OptionalTlv < BinData::Record
|
13
|
+
DEFAULT = 'default'
|
14
|
+
|
15
|
+
endian :big
|
16
|
+
|
17
|
+
bit8 :tlv_type
|
18
|
+
bit8 :tlv_info_length,
|
19
|
+
onlyif: -> { !(end_of_dhcpdu?) }
|
20
|
+
choice :tlv_value,
|
21
|
+
onlyif: -> { !(end_of_dhcpdu?) },
|
22
|
+
selection: :chooser do
|
23
|
+
uint8 Dhcp::MESSAGE_TYPE_TLV
|
24
|
+
ip_address Dhcp::SERVER_IDENTIFIER_TLV
|
25
|
+
uint32be Dhcp::RENEWAL_TIME_VALUE_TLV
|
26
|
+
uint32be Dhcp::REBINDING_TIME_VALUE_TLV
|
27
|
+
uint32be Dhcp::IP_ADDRESS_LEASE_TIME_TLV
|
28
|
+
ip_address Dhcp::SUBNET_MASK_TLV
|
29
|
+
ip_address Dhcp::REQUESTED_IP_ADDRESS_TLV
|
30
|
+
client_id Dhcp::CLIENT_IDENTIFIER_TLV
|
31
|
+
parameter_list Dhcp::PARAMETERS_LIST_TLV
|
32
|
+
dhcp_string DEFAULT
|
33
|
+
end
|
34
|
+
|
35
|
+
def end_of_dhcptlv?
|
36
|
+
tlv_type == Dhcp::END_OF_TLV
|
37
|
+
end
|
38
|
+
|
39
|
+
def chooser
|
40
|
+
if valid_optional_tlv?
|
41
|
+
tlv_type
|
42
|
+
else
|
43
|
+
DEFAULT
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def end_of_dhcpdu?
|
48
|
+
tlv_type == Dhcp::END_OF_TLV
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def valid_optional_tlv?
|
54
|
+
optional_tlv? || end_of_dhcptlv?
|
55
|
+
end
|
56
|
+
|
57
|
+
# rubocop:disable MethodLength
|
58
|
+
def optional_tlv?
|
59
|
+
[
|
60
|
+
Dhcp::MESSAGE_TYPE_TLV,
|
61
|
+
Dhcp::SERVER_IDENTIFIER_TLV,
|
62
|
+
Dhcp::CLIENT_IDENTIFIER_TLV,
|
63
|
+
Dhcp::RENEWAL_TIME_VALUE_TLV,
|
64
|
+
Dhcp::REBINDING_TIME_VALUE_TLV,
|
65
|
+
Dhcp::REQUESTED_IP_ADDRESS_TLV,
|
66
|
+
Dhcp::PARAMETERS_LIST_TLV,
|
67
|
+
Dhcp::IP_ADDRESS_LEASE_TIME_TLV,
|
68
|
+
Dhcp::SUBNET_MASK_TLV
|
69
|
+
].include?(tlv_type)
|
70
|
+
end
|
71
|
+
# rubocop:enable MethodLength
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'pio/type/mac_address'
|
4
|
+
|
5
|
+
module Pio
|
6
|
+
class Dhcp
|
7
|
+
# Dhcp Client Id Format
|
8
|
+
class ClientId < BinData::Primitive
|
9
|
+
bit8 :hardwaretype, value: 1
|
10
|
+
mac_address :mac
|
11
|
+
|
12
|
+
def get
|
13
|
+
mac
|
14
|
+
end
|
15
|
+
|
16
|
+
def set(value)
|
17
|
+
self.mac = value
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'bindata'
|
4
|
+
|
5
|
+
module Pio
|
6
|
+
module Type
|
7
|
+
# DHCP ParameterList Format.
|
8
|
+
class ParameterList < BinData::Primitive
|
9
|
+
array :octets,
|
10
|
+
type: :uint8,
|
11
|
+
initial_length: :tlv_info_length
|
12
|
+
|
13
|
+
def set(value)
|
14
|
+
self.octets = value
|
15
|
+
end
|
16
|
+
|
17
|
+
def get
|
18
|
+
octets
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'bindata'
|
4
|
+
|
5
|
+
module Pio
|
6
|
+
module Type
|
7
|
+
# DHCP String Format.
|
8
|
+
class DhcpString < BinData::Primitive
|
9
|
+
string :dhcp_string,
|
10
|
+
read_length: :tlv_info_length
|
11
|
+
|
12
|
+
def set(value)
|
13
|
+
self.dhcp_string = value
|
14
|
+
end
|
15
|
+
|
16
|
+
def get
|
17
|
+
dhcp_string
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|