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
@@ -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
|