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
data/examples/arp_new.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'pio'
|
2
|
+
|
3
|
+
request = Pio::Arp::Request.new(
|
4
|
+
source_mac: '00:26:82:eb:ea:d1',
|
5
|
+
sender_protocol_address: '192.168.83.3',
|
6
|
+
target_protocol_address: '192.168.83.254'
|
7
|
+
)
|
8
|
+
request.to_binary # => Arp Request frame in binary format.
|
9
|
+
|
10
|
+
reply = Pio::Arp::Reply.new(
|
11
|
+
source_mac: '00:16:9d:1d:9c:c4',
|
12
|
+
destination_mac: '00:26:82:eb:ea:d1',
|
13
|
+
sender_protocol_address: '192.168.83.254',
|
14
|
+
target_protocol_address: '192.168.83.3'
|
15
|
+
)
|
16
|
+
reply.to_binary # => Arp Reply frame in binary format.
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'pio'
|
2
|
+
|
3
|
+
discover = Pio::Dhcp::Discover.new(source_mac: '24:db:ac:41:e5:5b')
|
4
|
+
discover.to_binary # => DHCP Discover frame in binary format
|
5
|
+
|
6
|
+
offer = Pio::Dhcp::Offer.new(
|
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
|
+
transaction_id: discover.transaction_id
|
12
|
+
)
|
13
|
+
offer.to_binary # => DHCP Offer frame in binary format
|
14
|
+
|
15
|
+
request = Pio::Dhcp::Request.new(
|
16
|
+
source_mac: '24:db:ac:41:e5:5b',
|
17
|
+
server_identifier: '192.168.0.100',
|
18
|
+
requested_ip_address: '192.168.0.1',
|
19
|
+
transaction_id: offer.transaction_id
|
20
|
+
)
|
21
|
+
request.to_binary # => DHCP Request frame in binary format
|
22
|
+
|
23
|
+
ack = Pio::Dhcp::Ack.new(
|
24
|
+
source_mac: '00:26:82:eb:ea:d1',
|
25
|
+
destination_mac: '24:db:ac:41:e5:5b',
|
26
|
+
ip_source_address: '192.168.0.100',
|
27
|
+
ip_destination_address: '192.168.0.1',
|
28
|
+
transaction_id: request.transaction_id
|
29
|
+
)
|
30
|
+
ack.to_binary # => DHCP Ack frame in binary format
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'pio'
|
2
|
+
|
3
|
+
request = Pio::Icmp::Request.new(
|
4
|
+
source_mac: '00:16:9d:1d:9c:c4',
|
5
|
+
destination_mac: '00:26:82:eb:ea:d1',
|
6
|
+
ip_source_address: '192.168.83.3',
|
7
|
+
ip_destination_address: '192.168.83.254'
|
8
|
+
)
|
9
|
+
request.to_binary # => ICMP Request frame in binary format.
|
10
|
+
|
11
|
+
reply = Pio::Icmp::Reply.new(
|
12
|
+
source_mac: '00:26:82:eb:ea:d1',
|
13
|
+
destination_mac: '00:16:9d:1d:9c:c4',
|
14
|
+
ip_source_address: '192.168.83.254',
|
15
|
+
ip_destination_address: '192.168.83.3',
|
16
|
+
# The ICMP Identifier and the ICMP Sequence number
|
17
|
+
# should be same as those of the request.
|
18
|
+
identifier: request.icmp_identifier,
|
19
|
+
sequence_number: request.icmp_sequence_number
|
20
|
+
)
|
21
|
+
reply.to_binary # => ICMP Reply frame in binary format.
|
data/lib/pio.rb
CHANGED
@@ -1,15 +1,9 @@
|
|
1
|
-
#
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'pio/parse_error'
|
4
|
+
|
2
5
|
require 'pio/arp'
|
3
6
|
require 'pio/lldp'
|
4
7
|
require 'pio/icmp'
|
5
|
-
|
6
|
-
|
7
|
-
# Raised when the packet data is in wrong format.
|
8
|
-
class ParseError < StandardError; end
|
9
|
-
end
|
10
|
-
|
11
|
-
### Local variables:
|
12
|
-
### mode: Ruby
|
13
|
-
### coding: utf-8-unix
|
14
|
-
### indent-tabs-mode: nil
|
15
|
-
### End:
|
8
|
+
require 'pio/mac'
|
9
|
+
require 'pio/dhcp'
|
data/lib/pio/arp.rb
CHANGED
@@ -1,28 +1,16 @@
|
|
1
|
-
#
|
2
|
-
require 'English'
|
3
|
-
require 'rubygems'
|
4
|
-
require 'bindata'
|
1
|
+
# encoding: utf-8
|
5
2
|
|
3
|
+
require 'pio/arp/frame'
|
6
4
|
require 'pio/arp/request'
|
7
5
|
require 'pio/arp/reply'
|
8
|
-
require 'pio/
|
6
|
+
require 'pio/message_type_selector'
|
9
7
|
|
8
|
+
# Packet parser and generator library.
|
10
9
|
module Pio
|
11
10
|
# ARP parser and generator.
|
12
|
-
|
13
11
|
class Arp
|
14
|
-
|
15
|
-
|
16
|
-
Reply::OPERATION => Reply
|
17
|
-
}
|
18
|
-
class << self
|
19
|
-
include Util
|
20
|
-
end
|
12
|
+
extend MessageTypeSelector
|
13
|
+
message_type Request::OPERATION => Request, Reply::OPERATION => Reply
|
21
14
|
end
|
15
|
+
ARP = Arp
|
22
16
|
end
|
23
|
-
|
24
|
-
### Local variables:
|
25
|
-
### mode: Ruby
|
26
|
-
### coding: utf-8-unix
|
27
|
-
### indent-tabs-mode: nil
|
28
|
-
### End:
|
data/lib/pio/arp/frame.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
#
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'bindata'
|
2
4
|
require 'pio/type/ethernet_header'
|
3
5
|
require 'pio/type/ip_address'
|
4
6
|
require 'pio/type/mac_address'
|
@@ -11,11 +13,11 @@ module Pio
|
|
11
13
|
|
12
14
|
endian :big
|
13
15
|
|
14
|
-
ethernet_header :
|
15
|
-
uint16 :hardware_type, :
|
16
|
-
uint16 :protocol_type, :
|
17
|
-
uint8 :hardware_length, :
|
18
|
-
uint8 :protocol_length, :
|
16
|
+
ethernet_header ether_type: 0x0806
|
17
|
+
uint16 :hardware_type, value: 1
|
18
|
+
uint16 :protocol_type, value: 0x0800
|
19
|
+
uint8 :hardware_length, value: 6
|
20
|
+
uint8 :protocol_length, value: 4
|
19
21
|
uint16 :operation
|
20
22
|
mac_address :sender_hardware_address
|
21
23
|
ip_address :sender_protocol_address
|
@@ -32,9 +34,3 @@ module Pio
|
|
32
34
|
end
|
33
35
|
end
|
34
36
|
end
|
35
|
-
|
36
|
-
### Local variables:
|
37
|
-
### mode: Ruby
|
38
|
-
### coding: utf-8-unix
|
39
|
-
### indent-tabs-mode: nil
|
40
|
-
### End:
|
data/lib/pio/arp/message.rb
CHANGED
@@ -1,26 +1,13 @@
|
|
1
|
-
#
|
1
|
+
# encoding: utf-8
|
2
|
+
|
2
3
|
require 'forwardable'
|
3
4
|
require 'pio/arp/frame'
|
4
|
-
require 'pio/ipv4_address'
|
5
|
-
require 'pio/message_util'
|
6
5
|
|
7
6
|
module Pio
|
8
7
|
class Arp
|
9
8
|
# Base class of ARP Request and Reply
|
10
9
|
class Message
|
11
10
|
extend Forwardable
|
12
|
-
include MessageUtil
|
13
|
-
|
14
|
-
def self.create_from(frame)
|
15
|
-
message = allocate
|
16
|
-
message.instance_variable_set :@frame, frame
|
17
|
-
message
|
18
|
-
end
|
19
|
-
|
20
|
-
def initialize(options)
|
21
|
-
@options = options
|
22
|
-
@frame = Arp::Frame.new(option_hash)
|
23
|
-
end
|
24
11
|
|
25
12
|
def_delegators :@frame, :destination_mac
|
26
13
|
def_delegators :@frame, :source_mac
|
@@ -36,17 +23,17 @@ module Pio
|
|
36
23
|
def_delegators :@frame, :target_protocol_address
|
37
24
|
def_delegators :@frame, :to_binary
|
38
25
|
|
39
|
-
|
26
|
+
def self.create_from(frame)
|
27
|
+
message = allocate
|
28
|
+
message.instance_variable_set :@frame, frame
|
29
|
+
message
|
30
|
+
end
|
31
|
+
|
32
|
+
private_class_method :new
|
40
33
|
|
41
|
-
def
|
42
|
-
|
43
|
-
|
44
|
-
:destination_mac => Mac,
|
45
|
-
:sender_hardware_address => Mac,
|
46
|
-
:target_hardware_address => Mac,
|
47
|
-
:sender_protocol_address => IPv4Address,
|
48
|
-
:target_protocol_address => IPv4Address,
|
49
|
-
}
|
34
|
+
def initialize(user_options)
|
35
|
+
options = self.class.const_get(:Options).new(user_options.dup.freeze)
|
36
|
+
@frame = Arp::Frame.new(options.to_hash)
|
50
37
|
end
|
51
38
|
end
|
52
39
|
end
|
data/lib/pio/arp/reply.rb
CHANGED
@@ -1,45 +1,45 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
3
|
require 'pio/arp/message'
|
4
4
|
require 'pio/mac'
|
5
|
+
require 'pio/options'
|
5
6
|
|
6
7
|
module Pio
|
7
8
|
class Arp
|
8
9
|
# ARP Reply packet generator
|
9
10
|
class Reply < Message
|
10
11
|
OPERATION = 2
|
12
|
+
public_class_method :new
|
11
13
|
|
12
|
-
|
14
|
+
# User options for creating an Arp Reply.
|
15
|
+
class Options < Pio::Options
|
16
|
+
mandatory_option :source_mac
|
17
|
+
mandatory_option :destination_mac
|
18
|
+
mandatory_option :sender_protocol_address
|
19
|
+
mandatory_option :target_protocol_address
|
13
20
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
21
|
+
def initialize(options)
|
22
|
+
validate options
|
23
|
+
@source_mac = Mac.new(options[:source_mac]).freeze
|
24
|
+
@destination_mac = Mac.new(options[:destination_mac]).freeze
|
25
|
+
@sender_protocol_address =
|
26
|
+
IPv4Address.new(options[:sender_protocol_address]).freeze
|
27
|
+
@target_protocol_address =
|
28
|
+
IPv4Address.new(options[:target_protocol_address]).freeze
|
29
|
+
end
|
19
30
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
:sender_hardware_address,
|
32
|
-
:target_hardware_address,
|
33
|
-
:sender_protocol_address,
|
34
|
-
:target_protocol_address,
|
35
|
-
]
|
31
|
+
def to_hash
|
32
|
+
{
|
33
|
+
operation: OPERATION,
|
34
|
+
source_mac: @source_mac,
|
35
|
+
destination_mac: @destination_mac,
|
36
|
+
sender_hardware_address: @source_mac,
|
37
|
+
target_hardware_address: @destination_mac,
|
38
|
+
sender_protocol_address: @sender_protocol_address,
|
39
|
+
target_protocol_address: @target_protocol_address
|
40
|
+
}.freeze
|
41
|
+
end
|
36
42
|
end
|
37
43
|
end
|
38
44
|
end
|
39
45
|
end
|
40
|
-
|
41
|
-
### Local variables:
|
42
|
-
### mode: Ruby
|
43
|
-
### coding: utf-8-unix
|
44
|
-
### indent-tabs-mode: nil
|
45
|
-
### End:
|
data/lib/pio/arp/request.rb
CHANGED
@@ -1,45 +1,46 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
3
|
require 'pio/arp/message'
|
4
4
|
require 'pio/mac'
|
5
|
+
require 'pio/options'
|
5
6
|
|
6
7
|
module Pio
|
7
8
|
class Arp
|
8
9
|
# ARP Request packet generator
|
9
10
|
class Request < Message
|
10
11
|
OPERATION = 1
|
12
|
+
public_class_method :new
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
+
# User options for creating an Arp Request.
|
15
|
+
class Options < Pio::Options
|
16
|
+
mandatory_option :source_mac
|
17
|
+
mandatory_option :sender_protocol_address
|
18
|
+
mandatory_option :target_protocol_address
|
14
19
|
|
15
|
-
|
20
|
+
BROADCAST_MAC = Mac.new(0xffffffffffff).freeze
|
21
|
+
ALL_ZERO_MAC = Mac.new(0).freeze
|
16
22
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
23
|
+
def initialize(options)
|
24
|
+
validate options
|
25
|
+
@source_mac = Mac.new(options[:source_mac]).freeze
|
26
|
+
@sender_protocol_address =
|
27
|
+
IPv4Address.new(options[:sender_protocol_address]).freeze
|
28
|
+
@target_protocol_address =
|
29
|
+
IPv4Address.new(options[:target_protocol_address]).freeze
|
30
|
+
end
|
24
31
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
32
|
+
def to_hash
|
33
|
+
{
|
34
|
+
operation: OPERATION,
|
35
|
+
source_mac: @source_mac,
|
36
|
+
destination_mac: BROADCAST_MAC,
|
37
|
+
sender_hardware_address: @source_mac,
|
38
|
+
target_hardware_address: ALL_ZERO_MAC,
|
39
|
+
sender_protocol_address: @sender_protocol_address,
|
40
|
+
target_protocol_address: @target_protocol_address
|
41
|
+
}.freeze
|
42
|
+
end
|
36
43
|
end
|
37
44
|
end
|
38
45
|
end
|
39
46
|
end
|
40
|
-
|
41
|
-
### Local variables:
|
42
|
-
### mode: Ruby
|
43
|
-
### coding: utf-8-unix
|
44
|
-
### indent-tabs-mode: nil
|
45
|
-
### End:
|
data/lib/pio/dhcp.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Packet parser and generator library.
|
4
|
+
module Pio
|
5
|
+
# Dhcp parser and generator.
|
6
|
+
class Dhcp
|
7
|
+
MESSAGE_TYPE_TLV = 53
|
8
|
+
SERVER_IDENTIFIER_TLV = 54
|
9
|
+
CLIENT_IDENTIFIER_TLV = 61
|
10
|
+
RENEWAL_TIME_VALUE_TLV = 58
|
11
|
+
REBINDING_TIME_VALUE_TLV = 59
|
12
|
+
REQUESTED_IP_ADDRESS_TLV = 50
|
13
|
+
PARAMETERS_LIST_TLV = 55
|
14
|
+
IP_ADDRESS_LEASE_TIME_TLV = 51
|
15
|
+
SUBNET_MASK_TLV = 1
|
16
|
+
ROUTER_TLV = 3
|
17
|
+
NTP_SERVERS_TLV = 42
|
18
|
+
DNS_TLV = 6
|
19
|
+
END_OF_TLV = 255
|
20
|
+
|
21
|
+
PARAMETER_REQUEST_LIST =
|
22
|
+
[
|
23
|
+
SUBNET_MASK_TLV,
|
24
|
+
ROUTER_TLV,
|
25
|
+
DNS_TLV,
|
26
|
+
NTP_SERVERS_TLV
|
27
|
+
]
|
28
|
+
end
|
29
|
+
DHCP = Dhcp
|
30
|
+
end
|
31
|
+
|
32
|
+
require 'bindata'
|
33
|
+
require 'pio/dhcp/discover'
|
34
|
+
require 'pio/dhcp/offer'
|
35
|
+
require 'pio/dhcp/request'
|
36
|
+
require 'pio/dhcp/ack'
|
37
|
+
|
38
|
+
module Pio
|
39
|
+
# Dhcp parser and generator.
|
40
|
+
class Dhcp
|
41
|
+
MESSAGE_TYPE = {
|
42
|
+
Discover::TYPE => Discover,
|
43
|
+
Offer::TYPE => Offer,
|
44
|
+
Request::TYPE => Request,
|
45
|
+
Ack::TYPE => Ack
|
46
|
+
}
|
47
|
+
|
48
|
+
def self.read(raw_data)
|
49
|
+
begin
|
50
|
+
frame = const_get('Frame').read(raw_data)
|
51
|
+
rescue
|
52
|
+
raise Pio::ParseError, $ERROR_INFO.message
|
53
|
+
end
|
54
|
+
|
55
|
+
const_get('MESSAGE_TYPE')[frame.message_type].create_from(frame)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|