pio 0.2.7 → 0.3.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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -0
  3. data/.travis.yml +1 -0
  4. data/CONTRIBUTING.md +12 -0
  5. data/Gemfile +26 -23
  6. data/Guardfile +5 -0
  7. data/README.md +61 -19
  8. data/Rakefile +54 -56
  9. data/lib/pio/arp/frame.rb +8 -6
  10. data/lib/pio/arp/message.rb +9 -23
  11. data/lib/pio/arp/reply.rb +6 -15
  12. data/lib/pio/arp/request.rb +7 -16
  13. data/lib/pio/arp.rb +14 -17
  14. data/lib/pio/icmp/frame.rb +131 -0
  15. data/lib/pio/icmp/message.rb +100 -0
  16. data/lib/pio/icmp/reply.rb +17 -0
  17. data/lib/pio/icmp/request.rb +17 -0
  18. data/lib/pio/icmp.rb +27 -0
  19. data/lib/pio/ipv4_address.rb +22 -39
  20. data/lib/pio/lldp/chassis_id_tlv.rb +13 -16
  21. data/lib/pio/lldp/end_of_lldpdu_value.rb +4 -5
  22. data/lib/pio/lldp/frame.rb +21 -32
  23. data/lib/pio/lldp/management_address_value.rb +3 -4
  24. data/lib/pio/lldp/optional_tlv.rb +13 -22
  25. data/lib/pio/lldp/organizationally_specific_value.rb +3 -4
  26. data/lib/pio/lldp/port_description_value.rb +3 -4
  27. data/lib/pio/lldp/port_id_tlv.rb +6 -9
  28. data/lib/pio/lldp/system_capabilities_value.rb +3 -4
  29. data/lib/pio/lldp/system_description_value.rb +3 -4
  30. data/lib/pio/lldp/system_name_value.rb +3 -4
  31. data/lib/pio/lldp/ttl_tlv.rb +6 -9
  32. data/lib/pio/lldp.rb +20 -36
  33. data/lib/pio/mac.rb +30 -53
  34. data/lib/pio/message_util.rb +19 -0
  35. data/lib/pio/type/config.reek +4 -0
  36. data/lib/pio/type/ethernet_header.rb +7 -4
  37. data/lib/pio/type/ip_address.rb +5 -8
  38. data/lib/pio/type/ipv4_header.rb +37 -0
  39. data/lib/pio/type/mac_address.rb +7 -8
  40. data/lib/pio/util.rb +21 -0
  41. data/lib/pio/version.rb +2 -2
  42. data/lib/pio.rb +4 -4
  43. data/pio.gemspec +15 -17
  44. data/pio.org +499 -76
  45. data/pio.org_archive +86 -0
  46. data/rubocop-todo.yml +9 -0
  47. data/spec/pio/arp/reply_spec.rb +106 -118
  48. data/spec/pio/arp/request_spec.rb +90 -101
  49. data/spec/pio/arp_spec.rb +105 -113
  50. data/spec/pio/icmp/reply_spec.rb +132 -0
  51. data/spec/pio/icmp/request_spec.rb +131 -0
  52. data/spec/pio/icmp_spec.rb +159 -0
  53. data/spec/pio/ipv4_address_spec.rb +87 -97
  54. data/spec/pio/lldp_spec.rb +237 -186
  55. data/spec/pio/mac_spec.rb +82 -93
  56. data/spec/spec_helper.rb +10 -13
  57. metadata +20 -2
data/spec/pio/arp_spec.rb CHANGED
@@ -1,133 +1,125 @@
1
- require "pio"
2
-
3
-
4
- module Pio
5
- describe Arp do
6
- context ".read" do
7
- subject { Arp.read( data.pack( "C*" ) ) }
8
-
9
- context "with an ARP Request packet" do
10
- let( :data ) {
11
- [
12
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, # destination mac address
13
- 0x00, 0x26, 0x82, 0xeb, 0xea, 0xd1, # source mac address
14
- 0x08, 0x06, # ethernet type
15
- 0x00, 0x01, # arp hardware type
16
- 0x08, 0x00, # arp protocol type
17
- 0x06, # hardware address size
18
- 0x04, # protocol address size
19
- 0x00, 0x01, # operational code
20
- 0x00, 0x26, 0x82, 0xeb, 0xea, 0xd1, # sender hardware address
21
- 0xc0, 0xa8, 0x53, 0x03, # sender protocol address
22
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # target hardware address
23
- 0xc0, 0xa8, 0x53, 0xfe, # target protocol address
24
- ]
25
- }
26
-
27
- its( :class ) { should be Arp::Request }
28
- its( "destination_mac.to_s" ) { should eq "ff:ff:ff:ff:ff:ff" }
29
- its( "source_mac.to_s" ) { should eq "00:26:82:eb:ea:d1" }
30
- its( :ether_type ) { should eq 0x0806 }
31
- its( :hardware_type ) { should eq 1 }
32
- its( :protocol_type ) { should eq 0x800 }
33
- its( :hardware_length ) { should eq 6 }
34
- its( :protocol_length ) { should eq 4 }
35
- its( :operation ) { should eq 1 }
36
- its( "sender_hardware_address.to_s" ) { should eq "00:26:82:eb:ea:d1" }
37
- its( "sender_protocol_address.to_s" ) { should eq "192.168.83.3" }
38
- its( "target_hardware_address.to_s" ) { should eq "00:00:00:00:00:00" }
39
- its( "target_protocol_address.to_s" ) { should eq "192.168.83.254" }
1
+ # -*- coding: utf-8 -*-
2
+ require 'pio'
3
+
4
+ describe Pio::Arp do
5
+ context '.read' do
6
+ subject { Pio::Arp.read(data.pack('C*')) }
7
+
8
+ context 'with an ARP Request packet' do
9
+ let(:data) do
10
+ [
11
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, # destination mac address
12
+ 0x00, 0x26, 0x82, 0xeb, 0xea, 0xd1, # source mac address
13
+ 0x08, 0x06, # ethernet type
14
+ 0x00, 0x01, # arp hardware type
15
+ 0x08, 0x00, # arp protocol type
16
+ 0x06, # hardware address size
17
+ 0x04, # protocol address size
18
+ 0x00, 0x01, # operational code
19
+ 0x00, 0x26, 0x82, 0xeb, 0xea, 0xd1, # sender hardware address
20
+ 0xc0, 0xa8, 0x53, 0x03, # sender protocol address
21
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # target hardware address
22
+ 0xc0, 0xa8, 0x53, 0xfe, # target protocol address
23
+ ]
40
24
  end
41
25
 
26
+ its(:class) { should be Pio::Arp::Request }
27
+ its('destination_mac.to_s') { should eq 'ff:ff:ff:ff:ff:ff' }
28
+ its('source_mac.to_s') { should eq '00:26:82:eb:ea:d1' }
29
+ its(:ether_type) { should eq 0x0806 }
30
+ its(:hardware_type) { should eq 1 }
31
+ its(:protocol_type) { should eq 0x800 }
32
+ its(:hardware_length) { should eq 6 }
33
+ its(:protocol_length) { should eq 4 }
34
+ its(:operation) { should eq 1 }
35
+ its('sender_hardware_address.to_s') { should eq '00:26:82:eb:ea:d1' }
36
+ its('sender_protocol_address.to_s') { should eq '192.168.83.3' }
37
+ its('target_hardware_address.to_s') { should eq '00:00:00:00:00:00' }
38
+ its('target_protocol_address.to_s') { should eq '192.168.83.254' }
39
+ end
42
40
 
43
- context "with an ARP Reply packet" do
44
- let( :data ) {
45
- [
46
- 0x00, 0x26, 0x82, 0xeb, 0xea, 0xd1, # destination mac address
47
- 0x00, 0x16, 0x9d, 0x1d, 0x9c, 0xc4, # source mac address
48
- 0x08, 0x06, # ethernet type
49
- 0x00, 0x01, # arp hardware type
50
- 0x08, 0x00, # arp protocol type
51
- 0x06, # hardware address size
52
- 0x04, # protocol address size
53
- 0x00, 0x02, # operational code
54
- 0x00, 0x16, 0x9d, 0x1d, 0x9c, 0xc4, # sender hardware address
55
- 0xc0, 0xa8, 0x53, 0xfe, # sender protocol address
56
- 0x00, 0x26, 0x82, 0xeb, 0xea, 0xd1, # target hardware address
57
- 0xc0, 0xa8, 0x53, 0x03, # target protocol address
58
- ]
59
- }
60
-
61
- its( :class ) { should be Arp::Reply }
62
- its( "destination_mac.to_s" ) { should eq "00:26:82:eb:ea:d1" }
63
- its( "source_mac.to_s" ) { should eq "00:16:9d:1d:9c:c4" }
64
- its( :ether_type ) { should eq 0x0806 }
65
- its( :hardware_type ) { should eq 1 }
66
- its( :protocol_type ) { should eq 0x800 }
67
- its( :hardware_length ) { should eq 6 }
68
- its( :protocol_length ) { should eq 4 }
69
- its( :operation ) { should eq 2 }
70
- its( "sender_hardware_address.to_s" ) { should eq "00:16:9d:1d:9c:c4" }
71
- its( "sender_protocol_address.to_s" ) { should eq "192.168.83.254" }
72
- its( "target_hardware_address.to_s" ) { should eq "00:26:82:eb:ea:d1" }
73
- its( "target_protocol_address.to_s" ) { should eq "192.168.83.3" }
41
+ context 'with an ARP Reply packet' do
42
+ let(:data) do
43
+ [
44
+ 0x00, 0x26, 0x82, 0xeb, 0xea, 0xd1, # destination mac address
45
+ 0x00, 0x16, 0x9d, 0x1d, 0x9c, 0xc4, # source mac address
46
+ 0x08, 0x06, # ethernet type
47
+ 0x00, 0x01, # arp hardware type
48
+ 0x08, 0x00, # arp protocol type
49
+ 0x06, # hardware address size
50
+ 0x04, # protocol address size
51
+ 0x00, 0x02, # operational code
52
+ 0x00, 0x16, 0x9d, 0x1d, 0x9c, 0xc4, # sender hardware address
53
+ 0xc0, 0xa8, 0x53, 0xfe, # sender protocol address
54
+ 0x00, 0x26, 0x82, 0xeb, 0xea, 0xd1, # target hardware address
55
+ 0xc0, 0xa8, 0x53, 0x03, # target protocol address
56
+ ]
74
57
  end
75
58
 
59
+ its(:class) { should be Pio::Arp::Reply }
60
+ its('destination_mac.to_s') { should eq '00:26:82:eb:ea:d1' }
61
+ its('source_mac.to_s') { should eq '00:16:9d:1d:9c:c4' }
62
+ its(:ether_type) { should eq 0x0806 }
63
+ its(:hardware_type) { should eq 1 }
64
+ its(:protocol_type) { should eq 0x800 }
65
+ its(:hardware_length) { should eq 6 }
66
+ its(:protocol_length) { should eq 4 }
67
+ its(:operation) { should eq 2 }
68
+ its('sender_hardware_address.to_s') { should eq '00:16:9d:1d:9c:c4' }
69
+ its('sender_protocol_address.to_s') { should eq '192.168.83.254' }
70
+ its('target_hardware_address.to_s') { should eq '00:26:82:eb:ea:d1' }
71
+ its('target_protocol_address.to_s') { should eq '192.168.83.3' }
72
+ end
76
73
 
77
- context "with an ARP Request captured in real environment" do
78
- let( :data ) {
79
- [
80
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5c, 0x9a, 0xd8, 0xea,
81
- 0x37, 0x32, 0x08, 0x06, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04,
82
- 0x00, 0x01, 0x5c, 0x9a, 0xd8, 0xea, 0x37, 0x32, 0xc0, 0xa8,
83
- 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8,
84
- 0x00, 0xfe
85
- ]
86
- it { expect { subject }.not_to raise_error }
87
- }
74
+ context 'with an ARP Request captured in real environment' do
75
+ let(:data) do
76
+ [
77
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5c, 0x9a, 0xd8, 0xea,
78
+ 0x37, 0x32, 0x08, 0x06, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04,
79
+ 0x00, 0x01, 0x5c, 0x9a, 0xd8, 0xea, 0x37, 0x32, 0xc0, 0xa8,
80
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8,
81
+ 0x00, 0xfe
82
+ ]
88
83
  end
84
+ it { expect { subject }.not_to raise_error }
85
+ end
89
86
 
90
-
91
- context "with an ARP Request from a real OpenFlow switch" do
92
- let( :data ) {
93
- [
94
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x11, 0x22, 0x33, 0x44,
95
- 0x55, 0x66, 0x08, 0x06, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04,
96
- 0x00, 0x01, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xc0, 0xa8,
97
- 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8,
98
- 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
99
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100
- 0x00, 0x00, 0x00, 0x00
101
- ]
102
- it { expect { subject }.not_to raise_error }
103
- }
87
+ context 'with an ARP Request from a real OpenFlow switch' do
88
+ let(:data) do
89
+ [
90
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x11, 0x22, 0x33, 0x44,
91
+ 0x55, 0x66, 0x08, 0x06, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04,
92
+ 0x00, 0x01, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xc0, 0xa8,
93
+ 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8,
94
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96
+ 0x00, 0x00, 0x00, 0x00
97
+ ]
104
98
  end
99
+ it { expect { subject }.not_to raise_error }
100
+ end
105
101
 
106
-
107
- context "with an ARP Reply captured in real environment" do
108
- let( :data ) {
109
- [
110
- 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x5c, 0x9a, 0xd8, 0xea,
111
- 0x37, 0x32, 0x08, 0x06, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04,
112
- 0x00, 0x02, 0x5c, 0x9a, 0xd8, 0xea, 0x37, 0x32, 0xc0, 0xa8,
113
- 0x00, 0x01, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xc0, 0xa8,
114
- 0x00, 0xfe
115
- ]
116
- it { expect { subject }.not_to raise_error }
117
- }
102
+ context 'with an ARP Reply captured in real environment' do
103
+ let(:data) do
104
+ [
105
+ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x5c, 0x9a, 0xd8, 0xea,
106
+ 0x37, 0x32, 0x08, 0x06, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04,
107
+ 0x00, 0x02, 0x5c, 0x9a, 0xd8, 0xea, 0x37, 0x32, 0xc0, 0xa8,
108
+ 0x00, 0x01, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xc0, 0xa8,
109
+ 0x00, 0xfe
110
+ ]
118
111
  end
112
+ it { expect { subject }.not_to raise_error }
113
+ end
119
114
 
115
+ context 'with an invalid ARP packet' do
116
+ let(:data) { [] }
120
117
 
121
- context "with an invalid ARP packet" do
122
- let( :data ) { [] }
123
-
124
- it { expect { subject }.to raise_error( Pio::ParseError ) }
125
- end
118
+ it { expect { subject }.to raise_error(Pio::ParseError) }
126
119
  end
127
120
  end
128
121
  end
129
122
 
130
-
131
123
  ### Local variables:
132
124
  ### mode: Ruby
133
125
  ### coding: utf-8-unix
@@ -0,0 +1,132 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'pio/icmp/reply'
3
+
4
+ describe Pio::Icmp::Reply do
5
+ context '.new' do
6
+ subject do
7
+ Pio::Icmp::Reply.new(
8
+ :destination_mac => '00:26:82:eb:ea:d1',
9
+ :source_mac => '24:db:ac:41:e5:5b',
10
+ :ip_source_address => '8.8.8.8',
11
+ :ip_destination_address => '192.168.1.102',
12
+ :echo_data => echo_data
13
+ )
14
+ end
15
+
16
+ context 'with :echo_data' do
17
+ let(:echo_data) { 'abcdefghijklmnopqrstuvwabcdefghi' }
18
+
19
+ context '#to_binary' do
20
+ it 'returns an ICMP reply binary string' do
21
+ valid_icmp_reply_dump = [
22
+ # Destination MAC
23
+ 0x00, 0x26, 0x82, 0xeb, 0xea, 0xd1,
24
+ # Source MAC
25
+ 0x24, 0xdb, 0xac, 0x41, 0xe5, 0x5b,
26
+ # EtherType
27
+ 0x08, 0x00,
28
+ # IP Version&IP Header Length
29
+ 0x45,
30
+ # IP Type Of Service
31
+ 0x00,
32
+ # IP Total Length
33
+ 0x00, 0x3c,
34
+ # IP Identifier
35
+ 0x00, 0x00,
36
+ # IP Flag&IP Fragment
37
+ 0x00, 0x00,
38
+ # IP TTL
39
+ 0x80,
40
+ # IP Protocol
41
+ 0x01,
42
+ # IP Header Checksum
43
+ 0x68, 0xa3,
44
+ # IP Source Address
45
+ 0x08, 0x08, 0x08, 0x08,
46
+ # IP Destination Address
47
+ 0xc0, 0xa8, 0x01, 0x66,
48
+ # ICMP Type
49
+ 0x00,
50
+ # ICMP Code
51
+ 0x00,
52
+ # ICMP Checksum
53
+ 0x54, 0x5b,
54
+ # ICMP Identifier
55
+ 0x01, 0x00,
56
+ # ICMP Sequence Number
57
+ 0x00, 0x01,
58
+ # Echo Data
59
+ 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
60
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
61
+ 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75,
62
+ 0x76, 0x77, 0x61, 0x62, 0x63, 0x64, 0x65,
63
+ 0x66, 0x67, 0x68, 0x69
64
+ ]
65
+
66
+ expect(subject.to_binary.unpack('C*')).to eq valid_icmp_reply_dump
67
+ end
68
+ end
69
+ end
70
+
71
+ context 'with an empty :echo_data' do
72
+ let(:echo_data) { '' }
73
+
74
+ context '#to_binary' do
75
+ it 'returns an ICMP reply binary string' do
76
+ valid_icmp_reply_dump = [
77
+ # Destination MAC
78
+ # Destination MAC
79
+ 0x00, 0x26, 0x82, 0xeb, 0xea, 0xd1,
80
+ # Source MAC
81
+ 0x24, 0xdb, 0xac, 0x41, 0xe5, 0x5b,
82
+ # EtherType
83
+ 0x08, 0x00,
84
+ # IP Version&IP Header Length
85
+ 0x45,
86
+ # IP Type Of Service
87
+ 0x00,
88
+ # IP Total Length
89
+ 0x00, 0x32,
90
+ # IP Identifier
91
+ 0x00, 0x00,
92
+ # IP Flag&IP Fragment
93
+ 0x00, 0x00,
94
+ # IP TTL
95
+ 0x80,
96
+ # IP Protocol
97
+ 0x01,
98
+ # IP Header Checksum
99
+ 0x68, 0xad,
100
+ # IP Source Address
101
+ 0x08, 0x08, 0x08, 0x08,
102
+ # IP Destination Address
103
+ 0xc0, 0xa8, 0x01, 0x66,
104
+ # ICMP Type
105
+ 0x00,
106
+ # ICMP Code
107
+ 0x00,
108
+ # ICMP Checksum
109
+ 0xfe, 0xfe,
110
+ # ICMP Identifier
111
+ 0x01, 0x00,
112
+ # ICMP Sequence Number
113
+ 0x00, 0x01,
114
+ # Echo Data
115
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
116
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
117
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
118
+ 0x00, 0x00, 0x00, 0x00
119
+ ]
120
+
121
+ expect(subject.to_binary.unpack('C*')).to eq valid_icmp_reply_dump
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
127
+
128
+ ### Local variables:
129
+ ### mode: Ruby
130
+ ### coding: utf-8-unix
131
+ ### indent-tabs-mode: nil
132
+ ### End:
@@ -0,0 +1,131 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'pio/icmp/request'
3
+
4
+ describe Pio::Icmp::Request do
5
+ context '.new' do
6
+ subject do
7
+ Pio::Icmp::Request.new(
8
+ :destination_mac => '24:db:ac:41:e5:5b',
9
+ :source_mac => '74:e5:0b:2a:18:f8',
10
+ :ip_source_address => '192.168.1.101',
11
+ :ip_destination_address => '8.8.8.8',
12
+ :echo_data => echo_data
13
+ )
14
+ end
15
+
16
+ context 'with :echo_data' do
17
+ let(:echo_data) { 'abcdefghijklmnopqrstuvwabcdefghi' }
18
+
19
+ context '#to_binary' do
20
+ it 'returns an ICMP request binary string' do
21
+ valid_icmp_request_dump = [
22
+ # Destination MAC
23
+ 0x24, 0xdb, 0xac, 0x41, 0xe5, 0x5b,
24
+ # Source MAC
25
+ 0x74, 0xe5, 0x0b, 0x2a, 0x18, 0xf8,
26
+ # EtherType
27
+ 0x08, 0x00,
28
+ # IP Version&IP Header Length
29
+ 0x45,
30
+ # IP Type Of Service
31
+ 0x00,
32
+ # IP Total Length
33
+ 0x00, 0x3c,
34
+ # IP Identifier
35
+ 0x00, 0x00,
36
+ # IP Flag&IP Fragment
37
+ 0x00, 0x00,
38
+ # IP TTL
39
+ 0x80,
40
+ # IP Protocol
41
+ 0x01,
42
+ # IP Header Checksum
43
+ 0x68, 0xa4,
44
+ # IP Source Address
45
+ 0xc0, 0xa8, 0x01, 0x65,
46
+ # IP Destination Address
47
+ 0x08, 0x08, 0x08, 0x08,
48
+ # ICMP Type
49
+ 0x08,
50
+ # ICMP Code
51
+ 0x00,
52
+ # ICMP Checksum
53
+ 0x4c, 0x5b,
54
+ # ICMP Identifier
55
+ 0x01, 0x00,
56
+ # ICMP Sequence Number
57
+ 0x00, 0x01,
58
+ # Echo Data
59
+ 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
60
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
61
+ 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75,
62
+ 0x76, 0x77, 0x61, 0x62, 0x63, 0x64, 0x65,
63
+ 0x66, 0x67, 0x68, 0x69
64
+ ]
65
+
66
+ expect(subject.to_binary.unpack('C*')).to eq valid_icmp_request_dump
67
+ end
68
+ end
69
+ end
70
+
71
+ context 'with an emply :echo_data' do
72
+ let(:echo_data) { '' }
73
+
74
+ context '#to_binary' do
75
+ it 'returns an ICMP request binary string' do
76
+ valid_icmp_request_dump = [
77
+ # Destination MAC
78
+ 0x24, 0xdb, 0xac, 0x41, 0xe5, 0x5b,
79
+ # Source MAC
80
+ 0x74, 0xe5, 0x0b, 0x2a, 0x18, 0xf8,
81
+ # EtherType
82
+ 0x08, 0x00,
83
+ # IP Version&IP Header Length
84
+ 0x45,
85
+ # IP Type Of Service
86
+ 0x00,
87
+ # IP Total Length
88
+ 0x00, 0x32,
89
+ # IP Identifier
90
+ 0x00, 0x00,
91
+ # IP Flag&IP Fragment
92
+ 0x00, 0x00,
93
+ # IP TTL
94
+ 0x80,
95
+ # IP Protocol
96
+ 0x01,
97
+ # IP Header Checksum
98
+ 0x68, 0xae,
99
+ # IP Source Address
100
+ 0xc0, 0xa8, 0x01, 0x65,
101
+ # IP Destination Address
102
+ 0x08, 0x08, 0x08, 0x08,
103
+ # ICMP Type
104
+ 0x08,
105
+ # ICMP Code
106
+ 0x00,
107
+ # ICMP Checksum
108
+ 0xf6, 0xfe,
109
+ # ICMP Identifier
110
+ 0x01, 0x00,
111
+ # ICMP Sequence Number
112
+ 0x00, 0x01,
113
+ # Echo Data
114
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
115
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
116
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
117
+ 0x00, 0x00, 0x00, 0x00
118
+ ]
119
+
120
+ expect(subject.to_binary.unpack('C*')).to eq valid_icmp_request_dump
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
126
+
127
+ ### Local variables:
128
+ ### mode: Ruby
129
+ ### coding: utf-8-unix
130
+ ### indent-tabs-mode: nil
131
+ ### End:
@@ -0,0 +1,159 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'pio'
3
+
4
+ describe Pio::Icmp do
5
+ context '.read' do
6
+ subject { Pio::Icmp.read(data.pack('C*')) }
7
+
8
+ context 'with Icmp request frame' do
9
+ let(:data) do
10
+ [
11
+ # Destination MAC
12
+ 0x24, 0xdb, 0xac, 0x41, 0xe5, 0x5b,
13
+ # Source MAC
14
+ 0x00, 0x26, 0x82, 0xeb, 0xea, 0xd1,
15
+ # EtherType
16
+ 0x08, 0x00,
17
+ # IP Version&IP Header Length
18
+ 0x45,
19
+ # IP Type Of Service
20
+ 0x00,
21
+ # IP Total Length
22
+ 0x00, 0x3c,
23
+ # IP Identifier
24
+ 0x39, 0xd3,
25
+ # IP Flag&IP Fragment
26
+ 0x00, 0x00,
27
+ # IP TTL
28
+ 0x80,
29
+ # IP Protocol
30
+ 0x01,
31
+ # IP Header Checksum
32
+ 0x2e, 0xd0,
33
+ # IP Source Address
34
+ 0xc0, 0xa8, 0x01, 0x66,
35
+ # IP Destination Address
36
+ 0x08, 0x08, 0x08, 0x08,
37
+ # ICMP Type
38
+ 0x08,
39
+ # ICMP Code
40
+ 0x00,
41
+ # ICMP Checksum
42
+ 0x4c, 0x5b,
43
+ # ICMP Identifier
44
+ 0x01, 0x00,
45
+ # ICMP Sequence Number
46
+ 0x00, 0x01,
47
+ # Echo Data
48
+ 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
49
+ 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
50
+ 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72,
51
+ 0x73, 0x74, 0x75, 0x76, 0x77, 0x61,
52
+ 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
53
+ 0x68, 0x69
54
+ ]
55
+ end
56
+
57
+ its('destination_mac.to_s') { should eq '24:db:ac:41:e5:5b' }
58
+ its('source_mac.to_s') { should eq '00:26:82:eb:ea:d1' }
59
+ its(:ether_type) { should eq 0x0800 }
60
+ its(:ip_version) { should eq 0x4 }
61
+ its(:ip_header_length) { should eq 0x5 }
62
+ its(:ip_type_of_service) { should eq 0x0 }
63
+ its(:ip_total_length) { should eq 60 }
64
+ its(:ip_identifier) { should eq 0x39d3 }
65
+ its(:ip_fragment) { should eq 0 }
66
+ its(:ip_ttl) { should eq 128 }
67
+ its(:ip_protocol) { should eq 1 }
68
+ its(:ip_header_checksum) { should eq 0x2ed0 }
69
+ its('ip_source_address.to_s') { should eq '192.168.1.102' }
70
+ its('ip_destination_address.to_s') { should eq '8.8.8.8' }
71
+ its(:icmp_type) { should eq 8 }
72
+ its(:icmp_code) { should eq 0 }
73
+ its(:icmp_checksum) { should eq 0x4c5b }
74
+ its(:icmp_identifier) { should eq 0x0100 }
75
+ its(:icmp_sequence_number) { should eq 0x0001 }
76
+ its(:echo_data) { should eq 'abcdefghijklmnopqrstuvwabcdefghi' }
77
+ end
78
+
79
+ context 'with Icmp reply frame' do
80
+ let(:data) do
81
+ [
82
+ # Destination MAC
83
+ 0x00, 0x26, 0x82, 0xeb, 0xea, 0xd1,
84
+ # Source MAC
85
+ 0x24, 0xdb, 0xac, 0x41, 0xe5, 0x5b,
86
+ # EtherType
87
+ 0x08, 0x00,
88
+ # IP Version&IP Header Length
89
+ 0x45,
90
+ # IP Type Of Service
91
+ 0x00,
92
+ # IP Total Length
93
+ 0x00, 0x3c,
94
+ # IP Identifier
95
+ 0x00, 0x00,
96
+ # IP Flag&IP Fragment
97
+ 0x00, 0x00,
98
+ # IP TTL
99
+ 0x2d,
100
+ # IP Protocol
101
+ 0x01,
102
+ # IP Header Checksum
103
+ 0xbb, 0xa3,
104
+ # IP Source Address
105
+ 0x08, 0x08, 0x08, 0x08,
106
+ # IP Destination Address
107
+ 0xc0, 0xa8, 0x01, 0x66,
108
+ # ICMP Type
109
+ 0x00,
110
+ # ICMP Code
111
+ 0x00,
112
+ # ICMP Checksum
113
+ 0x54, 0x5b,
114
+ # ICMP Identifier
115
+ 0x01, 0x00,
116
+ # ICMP Sequence Number
117
+ 0x00, 0x01,
118
+ 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a,
119
+ 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74,
120
+ 0x75, 0x76, 0x77, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
121
+ 0x68, 0x69
122
+ ]
123
+ end
124
+
125
+ its('destination_mac.to_s') { should eq '00:26:82:eb:ea:d1' }
126
+ its('source_mac.to_s') { should eq '24:db:ac:41:e5:5b' }
127
+ its(:ether_type) { should eq 0x0800 }
128
+ its(:ip_version) { should eq 0x4 }
129
+ its(:ip_header_length) { should eq 0x5 }
130
+ its(:ip_type_of_service) { should eq 0 }
131
+ its(:ip_total_length) { should eq 60 }
132
+ its(:ip_identifier) { should eq 0 }
133
+ its(:ip_fragment) { should eq 0 }
134
+ its(:ip_ttl) { should eq 45 }
135
+ its(:ip_protocol) { should eq 1 }
136
+ its(:ip_header_checksum) { should eq 0xbba3 }
137
+ its('ip_source_address.to_s') { should eq '8.8.8.8' }
138
+ its('ip_destination_address.to_s') { should eq '192.168.1.102' }
139
+ its(:icmp_type) { should eq 0 }
140
+ its(:icmp_code) { should eq 0 }
141
+ its(:icmp_checksum) { should eq 0x545b }
142
+ its(:icmp_identifier) { should eq 0x0100 }
143
+ its(:icmp_sequence_number) { should eq 0x0001 }
144
+ its(:echo_data) { should eq 'abcdefghijklmnopqrstuvwabcdefghi' }
145
+ end
146
+
147
+ context 'with an invalid Icmp frame' do
148
+ let(:data) { [] }
149
+
150
+ it { expect { subject }.to raise_error(Pio::ParseError) }
151
+ end
152
+ end
153
+ end
154
+
155
+ ### Local variables:
156
+ ### mode: Ruby
157
+ ### coding: utf-8-unix
158
+ ### indent-tabs-mode: nil
159
+ ### End: