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_reply'
4
+
5
+ module Pio
6
+ class Dhcp
7
+ # Dhcp Ack packet generator
8
+ class Ack < BootReply
9
+ TYPE = 5
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,16 @@
1
+ # encoding: utf-8
2
+
3
+ require 'pio/dhcp/message'
4
+ require 'pio/dhcp/boot_reply_options'
5
+
6
+ module Pio
7
+ class Dhcp
8
+ # DHCP Reply Frame Base Class
9
+ class BootReply < Message
10
+ MESSAGE_TYPE = 2
11
+
12
+ # DHCP Options Class.
13
+ class Options < Dhcp::BootReplyOptions; end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,75 @@
1
+ # encoding: utf-8
2
+
3
+ require 'pio/options'
4
+ require 'pio/dhcp/common_options'
5
+ require 'pio/dhcp/dhcp_tlv_options'
6
+
7
+ module Pio
8
+ class Dhcp
9
+ # Options for creating a DHCP message.
10
+ class BootReplyOptions < Pio::Options
11
+ include CommonOptions
12
+ include DhcpTlvOptions
13
+
14
+ mandatory_option :source_mac
15
+ mandatory_option :destination_mac
16
+ mandatory_option :ip_source_address
17
+ mandatory_option :ip_destination_address
18
+ mandatory_option :type
19
+ option :subnet_mask
20
+ option :renewal_time_value
21
+ option :rebinding_time_value
22
+ option :ip_address_lease_time
23
+ option :server_identifier
24
+ option :transaction_id
25
+
26
+ def initialize(options)
27
+ @options = options
28
+ end
29
+
30
+ def to_hash
31
+ {
32
+ destination_mac: destination_mac,
33
+ source_mac: source_mac,
34
+ ip_destination_address: ip_destination_address,
35
+ ip_source_address: ip_source_address,
36
+ udp_src_port: BOOTPS,
37
+ udp_dst_port: BOOTPC,
38
+ dhcp: dhcp_data
39
+ }
40
+ end
41
+
42
+ private
43
+
44
+ def dhcp_field_values
45
+ {
46
+ message_type: BootReply::MESSAGE_TYPE,
47
+ transaction_id: transaction_id,
48
+ client_ip_address: QUAD_ZERO_IP_ADDRESS,
49
+ your_ip_address: ip_destination_address,
50
+ next_server_ip_address: QUAD_ZERO_IP_ADDRESS,
51
+ relay_agent_ip_address: QUAD_ZERO_IP_ADDRESS,
52
+ client_mac_address: source_mac,
53
+ optional_tlvs: options_for_optional_tlv
54
+ }
55
+ end
56
+
57
+ def options_for_optional_tlv
58
+ [
59
+ message_type_hash,
60
+ renewal_time_value_hash,
61
+ rebinding_time_value_hash,
62
+ ip_address_lease_time_hash,
63
+ dhcp_server_identifier_hash,
64
+ subnet_mask_hash
65
+ ].compact
66
+ end
67
+
68
+ def server_identifier
69
+ IPv4Address.new(
70
+ @options[:server_identifier] || ip_source_address
71
+ )
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,16 @@
1
+ # encoding: utf-8
2
+
3
+ require 'pio/dhcp/message'
4
+ require 'pio/dhcp/boot_request_options'
5
+
6
+ module Pio
7
+ class Dhcp
8
+ # DHCP Request Frame Base Class
9
+ class BootRequest < Message
10
+ MESSAGE_TYPE = 1
11
+
12
+ # DHCP Options Class.
13
+ class Options < Dhcp::BootRequestOptions; end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,69 @@
1
+ # encoding: utf-8
2
+
3
+ require 'pio/options'
4
+ require 'pio/dhcp/common_options'
5
+ require 'pio/dhcp/dhcp_tlv_options'
6
+
7
+ module Pio
8
+ class Dhcp
9
+ # Options for creating a DHCP message.
10
+ class BootRequestOptions < Pio::Options
11
+ include CommonOptions
12
+ include DhcpTlvOptions
13
+
14
+ mandatory_option :source_mac
15
+ mandatory_option :type
16
+ option :destination_mac
17
+ option :requested_ip_address
18
+ option :server_identifier
19
+ option :transaction_id
20
+
21
+ def initialize(options)
22
+ validate options
23
+ @options = options
24
+ end
25
+
26
+ def to_hash
27
+ {
28
+ destination_mac: destination_mac,
29
+ source_mac: source_mac,
30
+ ip_source_address: QUAD_ZERO_IP_ADDRESS,
31
+ ip_destination_address: BROADCAST_IP_ADDRESS,
32
+ udp_src_port: BOOTPC,
33
+ udp_dst_port: BOOTPS,
34
+ dhcp: dhcp_data
35
+ }
36
+ end
37
+
38
+ private
39
+
40
+ def dhcp_field_values
41
+ {
42
+ message_type: BootRequest::MESSAGE_TYPE,
43
+ transaction_id: transaction_id,
44
+ client_ip_address: QUAD_ZERO_IP_ADDRESS,
45
+ your_ip_address: QUAD_ZERO_IP_ADDRESS,
46
+ next_server_ip_address: QUAD_ZERO_IP_ADDRESS,
47
+ relay_agent_ip_address: QUAD_ZERO_IP_ADDRESS,
48
+ client_mac_address: source_mac,
49
+ optional_tlvs: options_for_optional_tlv
50
+ }
51
+ end
52
+
53
+ def options_for_optional_tlv
54
+ [
55
+ message_type_hash,
56
+ client_identifier_hash,
57
+ requested_ip_address_hash,
58
+ parameters_list_hash,
59
+ dhcp_server_identifier_hash
60
+ ].compact
61
+ end
62
+
63
+ def server_identifier
64
+ server_id = @options[:server_identifier]
65
+ IPv4Address.new(server_id) if server_id
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,71 @@
1
+ # encoding: utf-8
2
+
3
+ module Pio
4
+ class Dhcp
5
+ # DHCP Common Options.
6
+ module CommonOptions
7
+ BOOTPC = 68
8
+ BOOTPS = 67
9
+ QUAD_ZERO_IP_ADDRESS = IPv4Address.new(0)
10
+ BROADCAST_MAC_ADDRESS = Mac.new(0xffffffffffff)
11
+ BROADCAST_IP_ADDRESS = IPv4Address.new(0xffffffff)
12
+
13
+ def dhcp_data
14
+ Dhcp::DhcpField.new(dhcp_field_values)
15
+ end
16
+
17
+ def type
18
+ @options[:type]
19
+ end
20
+
21
+ def source_mac
22
+ Mac.new(@options[:source_mac])
23
+ end
24
+
25
+ def destination_mac
26
+ Mac.new(@options[:destination_mac] || BROADCAST_MAC_ADDRESS)
27
+ end
28
+
29
+ def ip_source_address
30
+ IPv4Address.new(@options[:ip_source_address])
31
+ end
32
+
33
+ def ip_destination_address
34
+ IPv4Address.new(@options[:ip_destination_address])
35
+ end
36
+
37
+ def server_identifier
38
+ IPv4Address.new(
39
+ @options[:server_identifier] || ip_source_address
40
+ )
41
+ end
42
+
43
+ def subnet_mask
44
+ subnet = @options[:subnet_mask]
45
+ IPv4Address.new(subnet) if subnet
46
+ end
47
+
48
+ def transaction_id
49
+ @options[:transaction_id]
50
+ end
51
+
52
+ def renewal_time_value
53
+ @options[:renewal_time_value]
54
+ end
55
+
56
+ def rebinding_time_value
57
+ @options[:rebinding_time_value]
58
+ end
59
+
60
+ def ip_address_lease_time
61
+ @options[:ip_address_lease_time]
62
+ end
63
+
64
+ def requested_ip_address
65
+ IPv4Address.new(
66
+ @options[:requested_ip_address] || QUAD_ZERO_IP_ADDRESS
67
+ )
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,83 @@
1
+ # encoding: utf-8
2
+
3
+ module Pio
4
+ class Dhcp
5
+ # Checksum Calculate Utility.
6
+ module CsumUtil
7
+ private
8
+
9
+ def ip_csum
10
+ ipv4_header_2bytewise_slices.reduce(:+)
11
+ end
12
+
13
+ def udp_csum
14
+ udp_header_2bytewise_slices.reduce(:+)
15
+ end
16
+
17
+ def ipv4_header_2bytewise_slices
18
+ [
19
+ ipversion_ipheaderlength_iptypeofservice, ip_total_length,
20
+ ip_identifier, ipflag_ipfragment,
21
+ ipttl_ipproto,
22
+ ip_source_address_upper,
23
+ ip_source_address_lower,
24
+ ip_destination_address_upper,
25
+ ip_destination_address_lower
26
+ ]
27
+ end
28
+
29
+ def ip_source_address_upper
30
+ ip_source_address.get.to_i >> 16
31
+ end
32
+
33
+ def ip_source_address_lower
34
+ ip_source_address.get.to_i & 0xffff
35
+ end
36
+
37
+ def ip_destination_address_upper
38
+ ip_destination_address.get.to_i >> 16
39
+ end
40
+
41
+ def ip_destination_address_lower
42
+ ip_destination_address.get.to_i & 0xffff
43
+ end
44
+
45
+ def ipversion_ipheaderlength_iptypeofservice
46
+ ip_version << 12 | ip_header_length << 8 | ip_type_of_service
47
+ end
48
+
49
+ def ipflag_ipfragment
50
+ ip_flag << 13 | ip_fragment
51
+ end
52
+
53
+ def ipttl_ipproto
54
+ ip_ttl << 8 | ip_protocol
55
+ end
56
+
57
+ def udp_header_2bytewise_slices
58
+ [
59
+ pseudo_header_2bytewise_slices,
60
+ udp_src_port,
61
+ udp_dst_port,
62
+ udp_len,
63
+ payload_2bytewise_slices
64
+ ]
65
+ end
66
+
67
+ def payload_2bytewise_slices
68
+ (dhcp.to_binary_s + trail_data).unpack('n*').reduce(:+)
69
+ end
70
+
71
+ def pseudo_header_2bytewise_slices
72
+ [
73
+ ip_source_address_upper,
74
+ ip_source_address_lower,
75
+ ip_destination_address_upper,
76
+ ip_destination_address_lower,
77
+ ip_protocol,
78
+ udp_len
79
+ ].pack('n*').unpack('n*').reduce(:+)
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,48 @@
1
+ # encoding: utf-8
2
+
3
+ require 'pio/dhcp/optional_tlv'
4
+ require 'pio/type/ip_address'
5
+ require 'pio/type/mac_address'
6
+
7
+ module Pio
8
+ class Dhcp
9
+ # DHCP Field
10
+ class DhcpField < BinData::Record
11
+ MAGIC_COOKIE = 0x63825363
12
+ ETHERNET = 1
13
+ MAC_ADDRESS_LENGTH = 6
14
+
15
+ endian :big
16
+
17
+ uint8 :message_type
18
+ uint8 :hw_addr_type,
19
+ initial_value: ETHERNET
20
+ uint8 :hw_addr_len,
21
+ initial_value: MAC_ADDRESS_LENGTH
22
+ uint8 :hops,
23
+ initial_value: 0
24
+ uint32be :transaction_id,
25
+ initial_value: rand(0xffffffff)
26
+ uint16be :seconds,
27
+ initial_value: 0
28
+ uint16be :bootp_flags,
29
+ initial_value: 0
30
+ ip_address :client_ip_address
31
+ ip_address :your_ip_address
32
+ ip_address :next_server_ip_address
33
+ ip_address :relay_agent_ip_address
34
+ mac_address :client_mac_address
35
+ string :client_mac_address_padding,
36
+ length: 10
37
+ string :server_host_name,
38
+ length: 64
39
+ string :boot_file_name,
40
+ length: 128
41
+ uint32be :magic_cookie,
42
+ value: MAGIC_COOKIE
43
+ array :optional_tlvs,
44
+ type: :optional_tlv,
45
+ read_until: -> { element.end_of_dhcptlv? }
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,84 @@
1
+ # encoding: utf-8
2
+
3
+ require 'pio/dhcp/common_options'
4
+
5
+ module Pio
6
+ class Dhcp
7
+ # DHCP TLV Methods.
8
+ module DhcpTlvOptions
9
+ include CommonOptions
10
+
11
+ def message_type_hash
12
+ {
13
+ tlv_type: Dhcp::MESSAGE_TYPE_TLV,
14
+ tlv_info_length: 1,
15
+ tlv_value: type
16
+ }
17
+ end
18
+
19
+ def client_identifier_hash
20
+ {
21
+ tlv_type: Dhcp::CLIENT_IDENTIFIER_TLV,
22
+ tlv_info_length: 7,
23
+ tlv_value: source_mac
24
+ }
25
+ end
26
+
27
+ def requested_ip_address_hash
28
+ {
29
+ tlv_type: Dhcp::REQUESTED_IP_ADDRESS_TLV,
30
+ tlv_info_length: 4,
31
+ tlv_value: requested_ip_address
32
+ }
33
+ end
34
+
35
+ def dhcp_server_identifier_hash
36
+ {
37
+ tlv_type: Dhcp::SERVER_IDENTIFIER_TLV,
38
+ tlv_info_length: 4,
39
+ tlv_value: server_identifier
40
+ } if server_identifier
41
+ end
42
+
43
+ def parameters_list_hash
44
+ {
45
+ tlv_type: Dhcp::PARAMETERS_LIST_TLV,
46
+ tlv_info_length: Dhcp::PARAMETER_REQUEST_LIST.length,
47
+ tlv_value: Dhcp::PARAMETER_REQUEST_LIST
48
+ }
49
+ end
50
+
51
+ def renewal_time_value_hash
52
+ {
53
+ tlv_type: Dhcp::RENEWAL_TIME_VALUE_TLV,
54
+ tlv_info_length: 4,
55
+ tlv_value: renewal_time_value
56
+ } if renewal_time_value
57
+ end
58
+
59
+ def rebinding_time_value_hash
60
+ {
61
+ tlv_type: Dhcp::REBINDING_TIME_VALUE_TLV,
62
+ tlv_info_length: 4,
63
+ tlv_value: rebinding_time_value
64
+ } if rebinding_time_value
65
+ end
66
+
67
+ def ip_address_lease_time_hash
68
+ {
69
+ tlv_type: Dhcp::IP_ADDRESS_LEASE_TIME_TLV,
70
+ tlv_info_length: 4,
71
+ tlv_value: ip_address_lease_time
72
+ }
73
+ end
74
+
75
+ def subnet_mask_hash
76
+ {
77
+ tlv_type: Dhcp::SUBNET_MASK_TLV,
78
+ tlv_info_length: 4,
79
+ tlv_value: subnet_mask
80
+ } if subnet_mask
81
+ end
82
+ end
83
+ end
84
+ end