pio 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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