packet-protocols 0.1.2 → 0.1.3
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.
- checksums.yaml +4 -4
- data/lib/packet-protocols.rb +2 -1
- data/lib/packet-protocols/arp.rb +32 -0
- data/lib/packet-protocols/ethernet.rb +42 -0
- data/lib/packet-protocols/icmp.rb +24 -0
- data/lib/packet-protocols/ipv4.rb +67 -0
- data/lib/packet-protocols/tcp.rb +62 -0
- data/lib/packet-protocols/udp.rb +16 -0
- data/lib/packet-protocols/version.rb +1 -1
- data/spec/arp_spec.rb +5 -7
- data/spec/ethernet_spec.rb +12 -14
- data/spec/icmp_spec.rb +5 -7
- data/spec/ipv4_spec.rb +5 -7
- data/spec/spec_helper.rb +1 -0
- data/spec/tcp_spec.rb +5 -7
- data/spec/udp_spec.rb +5 -7
- metadata +27 -11
- data/lib/arp.rb +0 -30
- data/lib/ethernet.rb +0 -40
- data/lib/icmp.rb +0 -22
- data/lib/ipv4.rb +0 -65
- data/lib/tcp.rb +0 -61
- data/lib/udp.rb +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 771b3be228c9d1a28e289cec47308b0df485616f
|
4
|
+
data.tar.gz: 3005168ed00e3d997c8deb73456621b57436dda0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 15a4a29ea950cfbaa8c51639b3a50a9081d22daa5d684a1420d36d15ad90fe444789b5658dcf84168f440415d4664c55b242190e719cbae656799c2ad71e5934
|
7
|
+
data.tar.gz: d80ac44b8b31f551614a17b6471f57bcecf473cc0c2750cbc0b27e4dd31b1346326d63be3eda84e3dce880430a670fc8dae713b7184a5d403778f5f18c08f57d
|
data/lib/packet-protocols.rb
CHANGED
@@ -1 +1,2 @@
|
|
1
|
-
|
1
|
+
require 'packet-protocols/version'
|
2
|
+
require 'packet-protocols/ethernet'
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'bindata-contrib'
|
2
|
+
|
3
|
+
module PacketProtocols
|
4
|
+
class Arp < BinData::Record
|
5
|
+
HARDWARES = { ethernet: 1 }
|
6
|
+
PROTOCOLS = { ipv4: 0x0800 }
|
7
|
+
OPERATIONS = { request: 1, reply: 2 }
|
8
|
+
|
9
|
+
endian :big
|
10
|
+
enum16 :hardware, list: HARDWARES, initial_value: -> { :ethernet }
|
11
|
+
enum16 :protocol, list: PROTOCOLS, initial_value: -> { :ipv4 }
|
12
|
+
uint8 :hardware_length, initial_value: 6
|
13
|
+
uint8 :protocol_length, initial_value: 4
|
14
|
+
enum16 :operation, list: OPERATIONS, initial_value: -> { :request }
|
15
|
+
mac_address :mac_source, onlyif: :ipv4_in_ethernet?
|
16
|
+
ipv4_address :ip_source, onlyif: :ipv4_in_ethernet?
|
17
|
+
mac_address :mac_destination, onlyif: :ipv4_in_ethernet?
|
18
|
+
ipv4_address :ip_destination, onlyif: :ipv4_in_ethernet?
|
19
|
+
|
20
|
+
virtual assert: (proc do
|
21
|
+
!ipv4_in_ethernet? || (hardware_length == 6 && protocol_length == 4)
|
22
|
+
end)
|
23
|
+
|
24
|
+
def ipv4_in_ethernet?
|
25
|
+
hardware == :ethernet && protocol == :ipv4
|
26
|
+
end
|
27
|
+
|
28
|
+
def length
|
29
|
+
28
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'packet-protocols/ipv4'
|
2
|
+
require 'packet-protocols/arp'
|
3
|
+
|
4
|
+
module PacketProtocols
|
5
|
+
class Ethernet < BinData::Record
|
6
|
+
PROTOCOLS = {
|
7
|
+
ipv4: 0x0800,
|
8
|
+
arp: 0x0806,
|
9
|
+
vlan: 0x8100
|
10
|
+
}
|
11
|
+
|
12
|
+
endian :big
|
13
|
+
mac_address 'mac_destination'
|
14
|
+
mac_address 'mac_source'
|
15
|
+
enum16 :protocol_internal, list: PROTOCOLS, initial_value: -> { :ipv4 }
|
16
|
+
|
17
|
+
struct :vlan, onlyif: :has_vlan? do
|
18
|
+
bit3 :pcp, initial_value: 0
|
19
|
+
bit1 :cfi, initial_value: 0
|
20
|
+
bit12 :id, initial_value: 0
|
21
|
+
enum16 :protocol, list: PROTOCOLS, initial_value: -> { :ipv4 }
|
22
|
+
end
|
23
|
+
|
24
|
+
choice :payload, selection: -> { protocol.to_s } do
|
25
|
+
ipv4 'ipv4'
|
26
|
+
arp 'arp'
|
27
|
+
rest :default
|
28
|
+
end
|
29
|
+
|
30
|
+
def has_vlan?
|
31
|
+
protocol_internal == :vlan
|
32
|
+
end
|
33
|
+
|
34
|
+
def protocol
|
35
|
+
has_vlan? ? vlan.protocol : protocol_internal
|
36
|
+
end
|
37
|
+
|
38
|
+
def length
|
39
|
+
14 + (has_vlan? ? 4 : 0) + payload.length
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'bindata-contrib'
|
2
|
+
|
3
|
+
module PacketProtocols
|
4
|
+
class Icmp < BinData::Record
|
5
|
+
TYPES = { echo_reply: 0, echo_request: 8 }
|
6
|
+
|
7
|
+
endian :big
|
8
|
+
enum8 :type, list: TYPES, initial_value: -> { :echo_request }
|
9
|
+
uint8 :code, initial_value: 0
|
10
|
+
uint16 :checksum
|
11
|
+
|
12
|
+
uint16 :identifier, onlyif: :echo?
|
13
|
+
uint16 :sequence_number, onlyif: :echo?
|
14
|
+
rest :data, onlyif: :echo?
|
15
|
+
|
16
|
+
def echo?
|
17
|
+
type == :echo_request || type == :echo_reply
|
18
|
+
end
|
19
|
+
|
20
|
+
def length
|
21
|
+
4 + (echo? ? 4 + data.length : 0)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'bindata-contrib'
|
2
|
+
require 'packet-protocols/icmp'
|
3
|
+
require 'packet-protocols/tcp'
|
4
|
+
require 'packet-protocols/udp'
|
5
|
+
|
6
|
+
module PacketProtocols
|
7
|
+
class Ipv4 < BinData::Record
|
8
|
+
PROTOCOLS = { icmp: 1, tcp: 6, udp: 17 }
|
9
|
+
|
10
|
+
endian :big
|
11
|
+
bit4 :version, asserted_value: 4
|
12
|
+
bit4 :header_length, initial_value: 5
|
13
|
+
bit6 :dscp
|
14
|
+
bit2 :ecn
|
15
|
+
uint16 :total_length, initial_value: -> { header_length_in_bytes + payload.length }
|
16
|
+
uint16 :identifier
|
17
|
+
bit1 :reserved
|
18
|
+
bool :df
|
19
|
+
bool :mf
|
20
|
+
bit13 :fragment_offset
|
21
|
+
uint8 :time_to_live, initial_value: 64
|
22
|
+
enum8 :protocol, list: PROTOCOLS, initial_value: -> { :tcp }
|
23
|
+
uint16 :checksum#, initial_value: :compute_checksum
|
24
|
+
ipv4_address :ip_source
|
25
|
+
ipv4_address :ip_destination
|
26
|
+
string :options, read_length: :options_length_in_bytes
|
27
|
+
choice :payload, selection: -> { protocol.to_s } do
|
28
|
+
icmp 'icmp'
|
29
|
+
tcp 'tcp'
|
30
|
+
udp 'udp'
|
31
|
+
rest :default
|
32
|
+
end
|
33
|
+
|
34
|
+
# virtual assert: :checksum_valid?
|
35
|
+
|
36
|
+
def header_length_in_bytes
|
37
|
+
header_length * 4
|
38
|
+
end
|
39
|
+
|
40
|
+
def options_length_in_bytes
|
41
|
+
header_length_in_bytes - options.rel_offset
|
42
|
+
end
|
43
|
+
|
44
|
+
def length
|
45
|
+
total_length
|
46
|
+
end
|
47
|
+
|
48
|
+
# def compute_checksum
|
49
|
+
# self.checksum = 0
|
50
|
+
# self.checksum = checksum_function
|
51
|
+
# end
|
52
|
+
#
|
53
|
+
# def checksum_valid?
|
54
|
+
# checksum_function == 0
|
55
|
+
# end
|
56
|
+
|
57
|
+
# private
|
58
|
+
#
|
59
|
+
# def checksum_function
|
60
|
+
# bin = to_binary_s
|
61
|
+
# dbytes = bin.unpack('S>*')
|
62
|
+
# acc = dbytes.inject(:+)
|
63
|
+
# acc = ((acc >> 16) & 0xffff) + (acc & 0xffff)
|
64
|
+
# ~acc & 0xffff
|
65
|
+
# end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'bindata-contrib'
|
2
|
+
|
3
|
+
module PacketProtocols
|
4
|
+
class Tcp < BinData::Record
|
5
|
+
endian :big
|
6
|
+
uint16 :source_port
|
7
|
+
uint16 :destination_port
|
8
|
+
uint32 :sequence_number
|
9
|
+
uint32 :acknowledge_number
|
10
|
+
bit4 :data_offset, initial_value: -> { 5 + options.length / 4 }
|
11
|
+
bit3 :reserved
|
12
|
+
bool :ns
|
13
|
+
bool :cwr
|
14
|
+
bool :ece
|
15
|
+
bool :urg
|
16
|
+
bool :ack
|
17
|
+
bool :psh
|
18
|
+
bool :rst
|
19
|
+
bool :syn
|
20
|
+
bool :fin
|
21
|
+
uint16 :window_size
|
22
|
+
uint16 :checksum#, initial_value: :compute_checksum
|
23
|
+
uint16 :urgent_pointer
|
24
|
+
string :options, read_length: :options_length_in_bytes
|
25
|
+
rest :payload
|
26
|
+
|
27
|
+
# virtual assert: :checksum_valid?
|
28
|
+
|
29
|
+
def header_length_in_bytes
|
30
|
+
data_offset * 4
|
31
|
+
end
|
32
|
+
|
33
|
+
def options_length_in_bytes
|
34
|
+
header_length_in_bytes - options.rel_offset
|
35
|
+
end
|
36
|
+
|
37
|
+
def length
|
38
|
+
header_length_in_bytes + options_length_in_bytes + payload.length
|
39
|
+
end
|
40
|
+
|
41
|
+
# def compute_checksum
|
42
|
+
# self.checksum = 0
|
43
|
+
# self.checksum = checksum_function
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# def checksum_valid?
|
47
|
+
# checksum_function == 0
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# private
|
51
|
+
#
|
52
|
+
# def checksum_function
|
53
|
+
# bin = to_binary_s
|
54
|
+
# dbytes = bin.unpack('S>*')
|
55
|
+
# acc = dbytes.inject(:+)
|
56
|
+
# acc = ((acc >> 16) & 0xffff) + (acc & 0xffff)
|
57
|
+
# ~acc & 0xffff
|
58
|
+
# end
|
59
|
+
|
60
|
+
# TODO: need IP parent for checksum
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'bindata'
|
2
|
+
|
3
|
+
module PacketProtocols
|
4
|
+
class Udp < BinData::Record
|
5
|
+
endian :big
|
6
|
+
uint16 :source_port
|
7
|
+
uint16 :destination_port
|
8
|
+
uint16 :len, initial_value: -> { 8 + payload.length }
|
9
|
+
uint16 :checksum
|
10
|
+
rest :payload
|
11
|
+
|
12
|
+
def length
|
13
|
+
len
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/spec/arp_spec.rb
CHANGED
@@ -1,6 +1,4 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
describe Arp do
|
1
|
+
describe PacketProtocols::Arp do
|
4
2
|
let(:binary) {
|
5
3
|
[
|
6
4
|
0, 1, # hardware
|
@@ -16,7 +14,7 @@ describe Arp do
|
|
16
14
|
}
|
17
15
|
|
18
16
|
it 'must read binary data' do
|
19
|
-
arp = Arp.read(binary)
|
17
|
+
arp = PacketProtocols::Arp.read(binary)
|
20
18
|
expect(arp.hardware).to eq(:ethernet)
|
21
19
|
expect(arp.protocol).to eq(:ipv4)
|
22
20
|
expect(arp.hardware_length).to eq(6)
|
@@ -30,7 +28,7 @@ describe Arp do
|
|
30
28
|
end
|
31
29
|
|
32
30
|
it 'must initialize with default values' do
|
33
|
-
arp = Arp.new
|
31
|
+
arp = PacketProtocols::Arp.new
|
34
32
|
expect(arp.hardware).to eq(:ethernet)
|
35
33
|
expect(arp.protocol).to eq(:ipv4)
|
36
34
|
expect(arp.hardware_length).to eq(6)
|
@@ -43,7 +41,7 @@ describe Arp do
|
|
43
41
|
end
|
44
42
|
|
45
43
|
it 'must be able to change accessors' do
|
46
|
-
arp = Arp.new
|
44
|
+
arp = PacketProtocols::Arp.new
|
47
45
|
arp.operation = :reply
|
48
46
|
expect(arp.operation).to eq(:reply)
|
49
47
|
arp.mac_source = '01:23:45:67:89:01'
|
@@ -53,7 +51,7 @@ describe Arp do
|
|
53
51
|
end
|
54
52
|
|
55
53
|
it 'must initialize with options' do
|
56
|
-
arp = Arp.new(operation: :reply, ip_source: '192.168.0.1')
|
54
|
+
arp = PacketProtocols::Arp.new(operation: :reply, ip_source: '192.168.0.1')
|
57
55
|
expect(arp.operation).to eq(:reply)
|
58
56
|
expect(arp.ip_source).to eq('192.168.0.1')
|
59
57
|
end
|
data/spec/ethernet_spec.rb
CHANGED
@@ -1,6 +1,4 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
describe Ethernet do
|
1
|
+
describe PacketProtocols::Ethernet do
|
4
2
|
let(:binary) {
|
5
3
|
[
|
6
4
|
0, 0, 0, 0, 0, 2, # mac_destination
|
@@ -25,7 +23,7 @@ describe Ethernet do
|
|
25
23
|
}
|
26
24
|
|
27
25
|
it 'must read binary data' do
|
28
|
-
eth = Ethernet.read(binary)
|
26
|
+
eth = PacketProtocols::Ethernet.read(binary)
|
29
27
|
expect(eth.mac_destination).to eq('00:00:00:00:00:02')
|
30
28
|
expect(eth.mac_source).to eq('00:00:00:00:00:01')
|
31
29
|
expect(eth.protocol).to eq(:arp)
|
@@ -36,7 +34,7 @@ describe Ethernet do
|
|
36
34
|
end
|
37
35
|
|
38
36
|
it 'must initialize with default values' do
|
39
|
-
eth = Ethernet.new
|
37
|
+
eth = PacketProtocols::Ethernet.new
|
40
38
|
expect(eth.mac_destination).to eq('00:00:00:00:00:00')
|
41
39
|
expect(eth.mac_source).to eq('00:00:00:00:00:00')
|
42
40
|
expect(eth.protocol).to eq(:ipv4)
|
@@ -45,13 +43,13 @@ describe Ethernet do
|
|
45
43
|
end
|
46
44
|
|
47
45
|
it 'must be able to change accessors' do
|
48
|
-
eth = Ethernet.new
|
46
|
+
eth = PacketProtocols::Ethernet.new
|
49
47
|
eth.mac_destination = '00:00:00:00:00:02'
|
50
48
|
expect(eth.mac_destination).to eq('00:00:00:00:00:02')
|
51
49
|
end
|
52
50
|
|
53
51
|
it 'must initialize with options' do
|
54
|
-
eth = Ethernet.new(mac_destination: '00:00:00:00:00:02')
|
52
|
+
eth = PacketProtocols::Ethernet.new(mac_destination: '00:00:00:00:00:02')
|
55
53
|
expect(eth.mac_destination).to eq('00:00:00:00:00:02')
|
56
54
|
end
|
57
55
|
end
|
@@ -59,9 +57,9 @@ end
|
|
59
57
|
|
60
58
|
# require 'spec_helper'
|
61
59
|
#
|
62
|
-
# describe Ethernet do
|
60
|
+
# describe PacketProtocols::Ethernet do
|
63
61
|
# it 'should read an unkown protocol' do
|
64
|
-
# packet = Ethernet.read [
|
62
|
+
# packet = PacketProtocols::Ethernet.read [
|
65
63
|
# 0, 0, 0, 0, 0, 2, # mac_destination
|
66
64
|
# 0, 0, 0, 0, 0, 1, # mac_source
|
67
65
|
# 0, 0 # protocol
|
@@ -73,7 +71,7 @@ end
|
|
73
71
|
# end
|
74
72
|
#
|
75
73
|
# it 'should read a VLAN packet' do
|
76
|
-
# packet = Ethernet.read [
|
74
|
+
# packet = PacketProtocols::Ethernet.read [
|
77
75
|
# 0, 0, 0, 0, 0, 2, # mac_destination
|
78
76
|
# 0, 0, 0, 0, 0, 1, # mac_source
|
79
77
|
# 0x81, 0, # protocol
|
@@ -93,7 +91,7 @@ end
|
|
93
91
|
#
|
94
92
|
# describe 'with ARP' do
|
95
93
|
# it 'should read binary' do
|
96
|
-
# packet = Ethernet.read [
|
94
|
+
# packet = PacketProtocols::Ethernet.read [
|
97
95
|
# 0, 0, 0, 0, 0, 2, # mac_destination
|
98
96
|
# 0, 0, 0, 0, 0, 1, # mac_source
|
99
97
|
# 8, 6, # protocol
|
@@ -126,7 +124,7 @@ end
|
|
126
124
|
#
|
127
125
|
# describe 'with IPv4/TCP' do
|
128
126
|
# it 'should read binary' do
|
129
|
-
# packet = Ethernet.read [
|
127
|
+
# packet = PacketProtocols::Ethernet.read [
|
130
128
|
# 0, 0, 0, 0, 0, 2, # mac_destination
|
131
129
|
# 0, 0, 0, 0, 0, 1, # mac_source
|
132
130
|
# 8, 0, # protocol
|
@@ -194,7 +192,7 @@ end
|
|
194
192
|
#
|
195
193
|
# describe 'with IPv4/UDP' do
|
196
194
|
# it 'should read binary' do
|
197
|
-
# packet = Ethernet.read [
|
195
|
+
# packet = PacketProtocols::Ethernet.read [
|
198
196
|
# 0, 0, 0, 0, 0, 2, # mac_destination
|
199
197
|
# 0, 0, 0, 0, 0, 1, # mac_source
|
200
198
|
# 8, 0, # protocol
|
@@ -244,7 +242,7 @@ end
|
|
244
242
|
#
|
245
243
|
# describe 'with IPv4/ICMP' do
|
246
244
|
# it 'should read binary' do
|
247
|
-
# packet = Ethernet.read [
|
245
|
+
# packet = PacketProtocols::Ethernet.read [
|
248
246
|
# 0, 0, 0, 0, 0, 2, # mac_destination
|
249
247
|
# 0, 0, 0, 0, 0, 1, # mac_source
|
250
248
|
# 8, 0, # protocol
|
data/spec/icmp_spec.rb
CHANGED
@@ -1,6 +1,4 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
describe Icmp do
|
1
|
+
describe PacketProtocols::Icmp do
|
4
2
|
let(:binary) {
|
5
3
|
[
|
6
4
|
0, # type
|
@@ -13,7 +11,7 @@ describe Icmp do
|
|
13
11
|
}
|
14
12
|
|
15
13
|
it 'must read binary data' do
|
16
|
-
icmp = Icmp.read(binary)
|
14
|
+
icmp = PacketProtocols::Icmp.read(binary)
|
17
15
|
expect(icmp.type).to eq(:echo_reply)
|
18
16
|
expect(icmp.code).to eq(0)
|
19
17
|
expect(icmp.checksum).to eq(0)
|
@@ -24,7 +22,7 @@ describe Icmp do
|
|
24
22
|
end
|
25
23
|
|
26
24
|
it 'must initialize with default values' do
|
27
|
-
icmp = Icmp.new
|
25
|
+
icmp = PacketProtocols::Icmp.new
|
28
26
|
expect(icmp.type).to eq(:echo_request)
|
29
27
|
expect(icmp.code).to eq(0)
|
30
28
|
expect(icmp.checksum).to eq(0)
|
@@ -34,7 +32,7 @@ describe Icmp do
|
|
34
32
|
end
|
35
33
|
|
36
34
|
it 'must be able to change accessors' do
|
37
|
-
icmp = Icmp.new
|
35
|
+
icmp = PacketProtocols::Icmp.new
|
38
36
|
icmp.type = :echo_reply
|
39
37
|
expect(icmp.type).to eq(:echo_reply)
|
40
38
|
icmp.data = [1, 2, 3, 4].pack('C*')
|
@@ -42,7 +40,7 @@ describe Icmp do
|
|
42
40
|
end
|
43
41
|
|
44
42
|
it 'must initialize with options' do
|
45
|
-
icmp = Icmp.new(type: :echo_reply, sequence_number: 123)
|
43
|
+
icmp = PacketProtocols::Icmp.new(type: :echo_reply, sequence_number: 123)
|
46
44
|
expect(icmp.type).to eq(:echo_reply)
|
47
45
|
expect(icmp.sequence_number).to eq(123)
|
48
46
|
end
|
data/spec/ipv4_spec.rb
CHANGED
@@ -1,6 +1,4 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
describe Ipv4 do
|
1
|
+
describe PacketProtocols::Ipv4 do
|
4
2
|
let(:binary) {
|
5
3
|
[
|
6
4
|
0x45, # version & header_length
|
@@ -24,7 +22,7 @@ describe Ipv4 do
|
|
24
22
|
}
|
25
23
|
|
26
24
|
it 'must read binary data' do
|
27
|
-
ipv4 = Ipv4.read(binary)
|
25
|
+
ipv4 = PacketProtocols::Ipv4.read(binary)
|
28
26
|
expect(ipv4.version).to eq(4)
|
29
27
|
expect(ipv4.header_length).to eq(5)
|
30
28
|
expect(ipv4.dscp).to eq(56)
|
@@ -45,7 +43,7 @@ describe Ipv4 do
|
|
45
43
|
end
|
46
44
|
|
47
45
|
it 'must initialize with default values' do
|
48
|
-
ipv4 = Ipv4.new
|
46
|
+
ipv4 = PacketProtocols::Ipv4.new
|
49
47
|
expect(ipv4.version).to eq(4)
|
50
48
|
expect(ipv4.header_length).to eq(5)
|
51
49
|
expect(ipv4.dscp).to eq(0)
|
@@ -65,13 +63,13 @@ describe Ipv4 do
|
|
65
63
|
end
|
66
64
|
|
67
65
|
it 'must be able to change accessors' do
|
68
|
-
ipv4 = Ipv4.new
|
66
|
+
ipv4 = PacketProtocols::Ipv4.new
|
69
67
|
ipv4.identifier = 10
|
70
68
|
expect(ipv4.identifier).to eq(10)
|
71
69
|
end
|
72
70
|
|
73
71
|
it 'must initialize with options' do
|
74
|
-
ipv4 = Ipv4.new(identifier: 10)
|
72
|
+
ipv4 = PacketProtocols::Ipv4.new(identifier: 10)
|
75
73
|
expect(ipv4.identifier).to eq(10)
|
76
74
|
end
|
77
75
|
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'packet-protocols'
|
data/spec/tcp_spec.rb
CHANGED
@@ -1,6 +1,4 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
describe Tcp do
|
1
|
+
describe PacketProtocols::Tcp do
|
4
2
|
let(:binary) {
|
5
3
|
[
|
6
4
|
0, 10, # source_port
|
@@ -16,7 +14,7 @@ describe Tcp do
|
|
16
14
|
}
|
17
15
|
|
18
16
|
it 'must read binary data' do
|
19
|
-
tcp = Tcp.read(binary)
|
17
|
+
tcp = PacketProtocols::Tcp.read(binary)
|
20
18
|
expect(tcp.source_port).to eq(10)
|
21
19
|
expect(tcp.destination_port).to eq(20)
|
22
20
|
expect(tcp.sequence_number).to eq(1)
|
@@ -40,19 +38,19 @@ describe Tcp do
|
|
40
38
|
end
|
41
39
|
|
42
40
|
it 'must initialize with default values' do
|
43
|
-
tcp = Tcp.new
|
41
|
+
tcp = PacketProtocols::Tcp.new
|
44
42
|
expect(tcp.source_port).to eq(0)
|
45
43
|
expect(tcp.data_offset).to eq(5)
|
46
44
|
end
|
47
45
|
|
48
46
|
it 'must be able to change accessors' do
|
49
|
-
tcp = Tcp.new
|
47
|
+
tcp = PacketProtocols::Tcp.new
|
50
48
|
tcp.source_port = 10
|
51
49
|
expect(tcp.source_port).to eq(10)
|
52
50
|
end
|
53
51
|
|
54
52
|
it 'must initialize with options' do
|
55
|
-
tcp = Tcp.new(source_port: 10, options: [1, 2, 3, 4].pack('C*'))
|
53
|
+
tcp = PacketProtocols::Tcp.new(source_port: 10, options: [1, 2, 3, 4].pack('C*'))
|
56
54
|
expect(tcp.source_port).to eq(10)
|
57
55
|
expect(tcp.data_offset).to eq(6)
|
58
56
|
expect(tcp.options).to eq([1, 2, 3, 4].pack('C*'))
|
data/spec/udp_spec.rb
CHANGED
@@ -1,6 +1,4 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
describe Udp do
|
1
|
+
describe PacketProtocols::Udp do
|
4
2
|
let(:binary) {
|
5
3
|
[
|
6
4
|
0, 10, # source_port
|
@@ -12,7 +10,7 @@ describe Udp do
|
|
12
10
|
}
|
13
11
|
|
14
12
|
it 'must read binary data' do
|
15
|
-
udp = Udp.read(binary)
|
13
|
+
udp = PacketProtocols::Udp.read(binary)
|
16
14
|
expect(udp.source_port).to eq(10)
|
17
15
|
expect(udp.destination_port).to eq(20)
|
18
16
|
expect(udp.length).to eq(12)
|
@@ -22,7 +20,7 @@ describe Udp do
|
|
22
20
|
end
|
23
21
|
|
24
22
|
it 'must initialize with default values' do
|
25
|
-
udp = Udp.new
|
23
|
+
udp = PacketProtocols::Udp.new
|
26
24
|
expect(udp.source_port).to eq(0)
|
27
25
|
expect(udp.destination_port).to eq(0)
|
28
26
|
expect(udp.length).to eq(8)
|
@@ -31,13 +29,13 @@ describe Udp do
|
|
31
29
|
end
|
32
30
|
|
33
31
|
it 'must be able to change accessors' do
|
34
|
-
udp = Udp.new
|
32
|
+
udp = PacketProtocols::Udp.new
|
35
33
|
udp.destination_port = 20
|
36
34
|
expect(udp.destination_port).to eq(20)
|
37
35
|
end
|
38
36
|
|
39
37
|
it 'must initialize with options' do
|
40
|
-
udp = Udp.new(source_port: 10, payload: [1, 2].pack('C*'))
|
38
|
+
udp = PacketProtocols::Udp.new(source_port: 10, payload: [1, 2].pack('C*'))
|
41
39
|
expect(udp.source_port).to eq(10)
|
42
40
|
expect(udp.length).to eq(10)
|
43
41
|
expect(udp.payload).to eq([1, 2].pack('C*'))
|
metadata
CHANGED
@@ -1,29 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: packet-protocols
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jérémy Pagé
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-01-
|
11
|
+
date: 2016-01-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bindata-contrib
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 0.1.2
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.1.2
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.4'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
22
36
|
version_requirements: !ruby/object:Gem::Requirement
|
23
37
|
requirements:
|
24
38
|
- - "~>"
|
25
39
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
40
|
+
version: '10.4'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: rspec
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -45,18 +59,19 @@ executables: []
|
|
45
59
|
extensions: []
|
46
60
|
extra_rdoc_files: []
|
47
61
|
files:
|
48
|
-
- lib/arp.rb
|
49
|
-
- lib/ethernet.rb
|
50
|
-
- lib/icmp.rb
|
51
|
-
- lib/ipv4.rb
|
52
62
|
- lib/packet-protocols.rb
|
63
|
+
- lib/packet-protocols/arp.rb
|
64
|
+
- lib/packet-protocols/ethernet.rb
|
65
|
+
- lib/packet-protocols/icmp.rb
|
66
|
+
- lib/packet-protocols/ipv4.rb
|
67
|
+
- lib/packet-protocols/tcp.rb
|
68
|
+
- lib/packet-protocols/udp.rb
|
53
69
|
- lib/packet-protocols/version.rb
|
54
|
-
- lib/tcp.rb
|
55
|
-
- lib/udp.rb
|
56
70
|
- spec/arp_spec.rb
|
57
71
|
- spec/ethernet_spec.rb
|
58
72
|
- spec/icmp_spec.rb
|
59
73
|
- spec/ipv4_spec.rb
|
74
|
+
- spec/spec_helper.rb
|
60
75
|
- spec/tcp_spec.rb
|
61
76
|
- spec/udp_spec.rb
|
62
77
|
homepage: https://github.com/jejepage/packet-protocols
|
@@ -88,5 +103,6 @@ test_files:
|
|
88
103
|
- spec/ethernet_spec.rb
|
89
104
|
- spec/icmp_spec.rb
|
90
105
|
- spec/ipv4_spec.rb
|
106
|
+
- spec/spec_helper.rb
|
91
107
|
- spec/tcp_spec.rb
|
92
108
|
- spec/udp_spec.rb
|
data/lib/arp.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
require 'bindata-contrib'
|
2
|
-
|
3
|
-
class Arp < BinData::Record
|
4
|
-
HARDWARES = { ethernet: 1 }
|
5
|
-
PROTOCOLS = { ipv4: 0x0800 }
|
6
|
-
OPERATIONS = { request: 1, reply: 2 }
|
7
|
-
|
8
|
-
endian :big
|
9
|
-
enum16 :hardware, list: HARDWARES, initial_value: -> { :ethernet }
|
10
|
-
enum16 :protocol, list: PROTOCOLS, initial_value: -> { :ipv4 }
|
11
|
-
uint8 :hardware_length, initial_value: 6
|
12
|
-
uint8 :protocol_length, initial_value: 4
|
13
|
-
enum16 :operation, list: OPERATIONS, initial_value: -> { :request }
|
14
|
-
mac_address :mac_source, onlyif: :ipv4_in_ethernet?
|
15
|
-
ipv4_address :ip_source, onlyif: :ipv4_in_ethernet?
|
16
|
-
mac_address :mac_destination, onlyif: :ipv4_in_ethernet?
|
17
|
-
ipv4_address :ip_destination, onlyif: :ipv4_in_ethernet?
|
18
|
-
|
19
|
-
virtual assert: (proc do
|
20
|
-
!ipv4_in_ethernet? || (hardware_length == 6 && protocol_length == 4)
|
21
|
-
end)
|
22
|
-
|
23
|
-
def ipv4_in_ethernet?
|
24
|
-
hardware == :ethernet && protocol == :ipv4
|
25
|
-
end
|
26
|
-
|
27
|
-
def length
|
28
|
-
28
|
29
|
-
end
|
30
|
-
end
|
data/lib/ethernet.rb
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
require_relative 'ipv4'
|
2
|
-
require_relative 'arp'
|
3
|
-
|
4
|
-
class Ethernet < BinData::Record
|
5
|
-
PROTOCOLS = {
|
6
|
-
ipv4: 0x0800,
|
7
|
-
arp: 0x0806,
|
8
|
-
vlan: 0x8100
|
9
|
-
}
|
10
|
-
|
11
|
-
endian :big
|
12
|
-
mac_address 'mac_destination'
|
13
|
-
mac_address 'mac_source'
|
14
|
-
enum16 :protocol_internal, list: PROTOCOLS, initial_value: -> { :ipv4 }
|
15
|
-
|
16
|
-
struct :vlan, onlyif: :has_vlan? do
|
17
|
-
bit3 :pcp, initial_value: 0
|
18
|
-
bit1 :cfi, initial_value: 0
|
19
|
-
bit12 :id, initial_value: 0
|
20
|
-
enum16 :protocol, list: PROTOCOLS, initial_value: -> { :ipv4 }
|
21
|
-
end
|
22
|
-
|
23
|
-
choice :payload, selection: -> { protocol.to_s } do
|
24
|
-
ipv4 'ipv4'
|
25
|
-
arp 'arp'
|
26
|
-
rest :default
|
27
|
-
end
|
28
|
-
|
29
|
-
def has_vlan?
|
30
|
-
protocol_internal == :vlan
|
31
|
-
end
|
32
|
-
|
33
|
-
def protocol
|
34
|
-
has_vlan? ? vlan.protocol : protocol_internal
|
35
|
-
end
|
36
|
-
|
37
|
-
def length
|
38
|
-
14 + (has_vlan? ? 4 : 0) + payload.length
|
39
|
-
end
|
40
|
-
end
|
data/lib/icmp.rb
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
require 'bindata-contrib'
|
2
|
-
|
3
|
-
class Icmp < BinData::Record
|
4
|
-
TYPES = { echo_reply: 0, echo_request: 8 }
|
5
|
-
|
6
|
-
endian :big
|
7
|
-
enum8 :type, list: TYPES, initial_value: -> { :echo_request }
|
8
|
-
uint8 :code, initial_value: 0
|
9
|
-
uint16 :checksum
|
10
|
-
|
11
|
-
uint16 :identifier, onlyif: :echo?
|
12
|
-
uint16 :sequence_number, onlyif: :echo?
|
13
|
-
rest :data, onlyif: :echo?
|
14
|
-
|
15
|
-
def echo?
|
16
|
-
type == :echo_request || type == :echo_reply
|
17
|
-
end
|
18
|
-
|
19
|
-
def length
|
20
|
-
4 + (echo? ? 4 + data.length : 0)
|
21
|
-
end
|
22
|
-
end
|
data/lib/ipv4.rb
DELETED
@@ -1,65 +0,0 @@
|
|
1
|
-
require 'bindata-contrib'
|
2
|
-
require_relative 'icmp'
|
3
|
-
require_relative 'tcp'
|
4
|
-
require_relative 'udp'
|
5
|
-
|
6
|
-
class Ipv4 < BinData::Record
|
7
|
-
PROTOCOLS = { icmp: 1, tcp: 6, udp: 17 }
|
8
|
-
|
9
|
-
endian :big
|
10
|
-
bit4 :version, asserted_value: 4
|
11
|
-
bit4 :header_length, initial_value: 5
|
12
|
-
bit6 :dscp
|
13
|
-
bit2 :ecn
|
14
|
-
uint16 :total_length, initial_value: -> { header_length_in_bytes + payload.length }
|
15
|
-
uint16 :identifier
|
16
|
-
bit1 :reserved
|
17
|
-
bool :df
|
18
|
-
bool :mf
|
19
|
-
bit13 :fragment_offset
|
20
|
-
uint8 :time_to_live, initial_value: 64
|
21
|
-
enum8 :protocol, list: PROTOCOLS, initial_value: -> { :tcp }
|
22
|
-
uint16 :checksum#, initial_value: :compute_checksum
|
23
|
-
ipv4_address :ip_source
|
24
|
-
ipv4_address :ip_destination
|
25
|
-
string :options, read_length: :options_length_in_bytes
|
26
|
-
choice :payload, selection: -> { protocol.to_s } do
|
27
|
-
icmp 'icmp'
|
28
|
-
tcp 'tcp'
|
29
|
-
udp 'udp'
|
30
|
-
rest :default
|
31
|
-
end
|
32
|
-
|
33
|
-
# virtual assert: :checksum_valid?
|
34
|
-
|
35
|
-
def header_length_in_bytes
|
36
|
-
header_length * 4
|
37
|
-
end
|
38
|
-
|
39
|
-
def options_length_in_bytes
|
40
|
-
header_length_in_bytes - options.rel_offset
|
41
|
-
end
|
42
|
-
|
43
|
-
def length
|
44
|
-
total_length
|
45
|
-
end
|
46
|
-
|
47
|
-
# def compute_checksum
|
48
|
-
# self.checksum = 0
|
49
|
-
# self.checksum = checksum_function
|
50
|
-
# end
|
51
|
-
#
|
52
|
-
# def checksum_valid?
|
53
|
-
# checksum_function == 0
|
54
|
-
# end
|
55
|
-
|
56
|
-
# private
|
57
|
-
#
|
58
|
-
# def checksum_function
|
59
|
-
# bin = to_binary_s
|
60
|
-
# dbytes = bin.unpack('S>*')
|
61
|
-
# acc = dbytes.inject(:+)
|
62
|
-
# acc = ((acc >> 16) & 0xffff) + (acc & 0xffff)
|
63
|
-
# ~acc & 0xffff
|
64
|
-
# end
|
65
|
-
end
|
data/lib/tcp.rb
DELETED
@@ -1,61 +0,0 @@
|
|
1
|
-
require 'bindata'
|
2
|
-
require 'bindata-contrib'
|
3
|
-
|
4
|
-
class Tcp < BinData::Record
|
5
|
-
endian :big
|
6
|
-
uint16 :source_port
|
7
|
-
uint16 :destination_port
|
8
|
-
uint32 :sequence_number
|
9
|
-
uint32 :acknowledge_number
|
10
|
-
bit4 :data_offset, initial_value: -> { 5 + options.length / 4 }
|
11
|
-
bit3 :reserved
|
12
|
-
bool :ns
|
13
|
-
bool :cwr
|
14
|
-
bool :ece
|
15
|
-
bool :urg
|
16
|
-
bool :ack
|
17
|
-
bool :psh
|
18
|
-
bool :rst
|
19
|
-
bool :syn
|
20
|
-
bool :fin
|
21
|
-
uint16 :window_size
|
22
|
-
uint16 :checksum#, initial_value: :compute_checksum
|
23
|
-
uint16 :urgent_pointer
|
24
|
-
string :options, read_length: :options_length_in_bytes
|
25
|
-
rest :payload
|
26
|
-
|
27
|
-
# virtual assert: :checksum_valid?
|
28
|
-
|
29
|
-
def header_length_in_bytes
|
30
|
-
data_offset * 4
|
31
|
-
end
|
32
|
-
|
33
|
-
def options_length_in_bytes
|
34
|
-
header_length_in_bytes - options.rel_offset
|
35
|
-
end
|
36
|
-
|
37
|
-
def length
|
38
|
-
header_length_in_bytes + options_length_in_bytes + payload.length
|
39
|
-
end
|
40
|
-
|
41
|
-
# def compute_checksum
|
42
|
-
# self.checksum = 0
|
43
|
-
# self.checksum = checksum_function
|
44
|
-
# end
|
45
|
-
#
|
46
|
-
# def checksum_valid?
|
47
|
-
# checksum_function == 0
|
48
|
-
# end
|
49
|
-
#
|
50
|
-
# private
|
51
|
-
#
|
52
|
-
# def checksum_function
|
53
|
-
# bin = to_binary_s
|
54
|
-
# dbytes = bin.unpack('S>*')
|
55
|
-
# acc = dbytes.inject(:+)
|
56
|
-
# acc = ((acc >> 16) & 0xffff) + (acc & 0xffff)
|
57
|
-
# ~acc & 0xffff
|
58
|
-
# end
|
59
|
-
|
60
|
-
# TODO: need IP parent for checksum
|
61
|
-
end
|
data/lib/udp.rb
DELETED