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.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +46 -12
  3. data/README.md +131 -116
  4. data/Rakefile +7 -92
  5. data/examples/arp_new.rb +16 -0
  6. data/examples/arp_read.rb +4 -0
  7. data/examples/dhcp_new.rb +30 -0
  8. data/examples/dhcp_read.rb +4 -0
  9. data/examples/icmp_new.rb +21 -0
  10. data/examples/icmp_read.rb +4 -0
  11. data/examples/lldp_new.rb +4 -0
  12. data/examples/lldp_read.rb +4 -0
  13. data/lib/pio.rb +6 -12
  14. data/lib/pio/arp.rb +7 -19
  15. data/lib/pio/arp/frame.rb +8 -12
  16. data/lib/pio/arp/message.rb +12 -25
  17. data/lib/pio/arp/reply.rb +30 -30
  18. data/lib/pio/arp/request.rb +30 -29
  19. data/lib/pio/dhcp.rb +58 -0
  20. data/lib/pio/dhcp/ack.rb +12 -0
  21. data/lib/pio/dhcp/boot_reply.rb +16 -0
  22. data/lib/pio/dhcp/boot_reply_options.rb +75 -0
  23. data/lib/pio/dhcp/boot_request.rb +16 -0
  24. data/lib/pio/dhcp/boot_request_options.rb +69 -0
  25. data/lib/pio/dhcp/common_options.rb +71 -0
  26. data/lib/pio/dhcp/csum_util.rb +83 -0
  27. data/lib/pio/dhcp/dhcp_field.rb +48 -0
  28. data/lib/pio/dhcp/dhcp_tlv_options.rb +84 -0
  29. data/lib/pio/dhcp/discover.rb +12 -0
  30. data/lib/pio/dhcp/field_util.rb +102 -0
  31. data/lib/pio/dhcp/frame.rb +95 -0
  32. data/lib/pio/dhcp/message.rb +79 -0
  33. data/lib/pio/dhcp/offer.rb +12 -0
  34. data/lib/pio/dhcp/optional_tlv.rb +74 -0
  35. data/lib/pio/dhcp/request.rb +12 -0
  36. data/lib/pio/dhcp/type/dhcp_client_id.rb +21 -0
  37. data/lib/pio/dhcp/type/dhcp_param_list.rb +22 -0
  38. data/lib/pio/dhcp/type/dhcp_string.rb +21 -0
  39. data/lib/pio/icmp.rb +7 -18
  40. data/lib/pio/icmp/frame.rb +38 -40
  41. data/lib/pio/icmp/message.rb +10 -61
  42. data/lib/pio/icmp/options.rb +25 -0
  43. data/lib/pio/icmp/reply.rb +34 -7
  44. data/lib/pio/icmp/request.rb +43 -7
  45. data/lib/pio/ipv4_address.rb +5 -8
  46. data/lib/pio/lldp.rb +22 -62
  47. data/lib/pio/lldp/chassis_id_tlv.rb +7 -13
  48. data/lib/pio/lldp/end_of_lldpdu_value.rb +3 -9
  49. data/lib/pio/lldp/frame.rb +6 -12
  50. data/lib/pio/lldp/management_address_value.rb +4 -10
  51. data/lib/pio/lldp/optional_tlv.rb +5 -10
  52. data/lib/pio/lldp/options.rb +37 -0
  53. data/lib/pio/lldp/organizationally_specific_value.rb +2 -8
  54. data/lib/pio/lldp/port_description_value.rb +2 -8
  55. data/lib/pio/lldp/port_id_tlv.rb +6 -12
  56. data/lib/pio/lldp/system_capabilities_value.rb +2 -8
  57. data/lib/pio/lldp/system_description_value.rb +2 -8
  58. data/lib/pio/lldp/system_name_value.rb +2 -8
  59. data/lib/pio/lldp/ttl_tlv.rb +5 -11
  60. data/lib/pio/mac.rb +4 -9
  61. data/lib/pio/message_type_selector.rb +22 -0
  62. data/lib/pio/options.rb +65 -0
  63. data/lib/pio/parse_error.rb +6 -0
  64. data/lib/pio/type/ethernet_header.rb +3 -2
  65. data/lib/pio/type/ip_address.rb +4 -9
  66. data/lib/pio/type/ipv4_header.rb +12 -17
  67. data/lib/pio/type/mac_address.rb +5 -10
  68. data/lib/pio/type/udp_header.rb +18 -0
  69. data/lib/pio/version.rb +3 -8
  70. data/pio.gemspec +12 -10
  71. data/spec/pio/arp/reply/options_spec.rb +145 -0
  72. data/spec/pio/arp/reply_spec.rb +77 -113
  73. data/spec/pio/arp/request/options_spec.rb +115 -0
  74. data/spec/pio/arp/request_spec.rb +74 -96
  75. data/spec/pio/arp_spec.rb +71 -105
  76. data/spec/pio/dhcp/ack_spec.rb +189 -0
  77. data/spec/pio/dhcp/discover_spec.rb +165 -0
  78. data/spec/pio/dhcp/offer_spec.rb +189 -0
  79. data/spec/pio/dhcp/request_spec.rb +173 -0
  80. data/spec/pio/dhcp_spec.rb +609 -0
  81. data/spec/pio/icmp/reply_spec.rb +102 -95
  82. data/spec/pio/icmp/request_spec.rb +86 -78
  83. data/spec/pio/icmp_spec.rb +153 -146
  84. data/spec/pio/ipv4_address_spec.rb +2 -7
  85. data/spec/pio/lldp/options_spec.rb +188 -0
  86. data/spec/pio/lldp_spec.rb +181 -208
  87. data/spec/pio/mac_spec.rb +3 -8
  88. data/spec/spec_helper.rb +4 -10
  89. metadata +69 -17
  90. data/.gitignore +0 -20
  91. data/.rspec +0 -3
  92. data/.rubocop.yml +0 -1
  93. data/.travis.yml +0 -13
  94. data/Gemfile +0 -37
  95. data/Guardfile +0 -24
  96. data/lib/pio/message_util.rb +0 -19
  97. data/lib/pio/type/config.reek +0 -4
  98. data/lib/pio/util.rb +0 -21
  99. data/pio.org +0 -668
  100. data/pio.org_archive +0 -943
  101. data/rubocop-todo.yml +0 -9
@@ -0,0 +1,12 @@
1
+ # encoding: utf-8
2
+
3
+ require 'pio/dhcp/boot_request'
4
+
5
+ module Pio
6
+ class Dhcp
7
+ # Dhcp Discover packet generator
8
+ class Discover < BootRequest
9
+ TYPE = 1
10
+ end
11
+ end
12
+ end
@@ -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,12 @@
1
+ # encoding: utf-8
2
+
3
+ require 'pio/dhcp/boot_reply'
4
+
5
+ module Pio
6
+ class Dhcp
7
+ # Dhcp Offer packet generator
8
+ class Offer < BootReply
9
+ TYPE = 2
10
+ end
11
+ end
12
+ 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,12 @@
1
+ # encoding: utf-8
2
+
3
+ require 'pio/dhcp/boot_request'
4
+
5
+ module Pio
6
+ class Dhcp
7
+ # Dhcp Request packet generator
8
+ class Request < BootRequest
9
+ TYPE = 3
10
+ end
11
+ end
12
+ 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