pio 0.2.7 → 0.3.0

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