packetgen 3.3.3 → 4.1.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.
- checksums.yaml +4 -4
- data/README.md +38 -22
- data/lib/packetgen/capture.rb +2 -2
- data/lib/packetgen/config.rb +0 -1
- data/lib/packetgen/deprecation.rb +14 -8
- data/lib/packetgen/header/arp.rb +17 -18
- data/lib/packetgen/header/asn1_base.rb +2 -1
- data/lib/packetgen/header/base.rb +42 -40
- data/lib/packetgen/header/bootp.rb +35 -37
- data/lib/packetgen/header/dhcp/option.rb +21 -21
- data/lib/packetgen/header/dhcp/options.rb +3 -3
- data/lib/packetgen/header/dhcp.rb +8 -9
- data/lib/packetgen/header/dhcpv6/duid.rb +16 -16
- data/lib/packetgen/header/dhcpv6/option.rb +83 -61
- data/lib/packetgen/header/dhcpv6/options.rb +4 -4
- data/lib/packetgen/header/dhcpv6/relay.rb +6 -5
- data/lib/packetgen/header/dhcpv6.rb +17 -18
- data/lib/packetgen/header/dns/name.rb +21 -16
- data/lib/packetgen/header/dns/opt.rb +5 -2
- data/lib/packetgen/header/dns/option.rb +14 -14
- data/lib/packetgen/header/dns/qdsection.rb +3 -3
- data/lib/packetgen/header/dns/question.rb +7 -8
- data/lib/packetgen/header/dns/rr.rb +56 -43
- data/lib/packetgen/header/dns/rrsection.rb +6 -6
- data/lib/packetgen/header/dns.rb +103 -90
- data/lib/packetgen/header/dot11/control.rb +12 -12
- data/lib/packetgen/header/dot11/data.rb +25 -24
- data/lib/packetgen/header/dot11/element.rb +4 -4
- data/lib/packetgen/header/dot11/management.rb +21 -18
- data/lib/packetgen/header/dot11/sub_mngt.rb +40 -53
- data/lib/packetgen/header/dot11.rb +117 -122
- data/lib/packetgen/header/dot1q.rb +12 -13
- data/lib/packetgen/header/dot1x.rb +13 -13
- data/lib/packetgen/header/eap/fast.rb +4 -4
- data/lib/packetgen/header/eap/md5.rb +16 -8
- data/lib/packetgen/header/eap/tls.rb +18 -19
- data/lib/packetgen/header/eap/ttls.rb +22 -21
- data/lib/packetgen/header/eap.rb +73 -48
- data/lib/packetgen/header/eth.rb +41 -27
- data/lib/packetgen/header/gre.rb +33 -11
- data/lib/packetgen/header/http/headers.rb +7 -6
- data/lib/packetgen/header/http/request.rb +38 -29
- data/lib/packetgen/header/http/response.rb +35 -27
- data/lib/packetgen/header/http/verbs.rb +1 -3
- data/lib/packetgen/header/icmp.rb +14 -14
- data/lib/packetgen/header/icmpv6.rb +10 -9
- data/lib/packetgen/header/igmp.rb +26 -15
- data/lib/packetgen/header/igmpv3/group_record.rb +18 -13
- data/lib/packetgen/header/igmpv3/mq.rb +16 -18
- data/lib/packetgen/header/igmpv3/mr.rb +5 -5
- data/lib/packetgen/header/igmpv3.rb +12 -11
- data/lib/packetgen/header/ip/addr.rb +19 -15
- data/lib/packetgen/header/ip/option.rb +47 -36
- data/lib/packetgen/header/ip/options.rb +1 -1
- data/lib/packetgen/header/ip.rb +77 -95
- data/lib/packetgen/header/ipv6/addr.rb +28 -27
- data/lib/packetgen/header/ipv6/extension.rb +13 -11
- data/lib/packetgen/header/ipv6/hop_by_hop.rb +32 -13
- data/lib/packetgen/header/ipv6.rb +42 -35
- data/lib/packetgen/header/llc.rb +28 -21
- data/lib/packetgen/header/mdns.rb +10 -3
- data/lib/packetgen/header/mld.rb +15 -13
- data/lib/packetgen/header/mldv2/mcast_address_record.rb +17 -12
- data/lib/packetgen/header/mldv2/mlq.rb +22 -24
- data/lib/packetgen/header/mldv2/mlr.rb +8 -8
- data/lib/packetgen/header/mldv2.rb +1 -1
- data/lib/packetgen/header/ospfv2/db_description.rb +17 -18
- data/lib/packetgen/header/ospfv2/hello.rb +18 -17
- data/lib/packetgen/header/ospfv2/ls_ack.rb +6 -7
- data/lib/packetgen/header/ospfv2/ls_request.rb +14 -13
- data/lib/packetgen/header/ospfv2/ls_update.rb +9 -9
- data/lib/packetgen/header/ospfv2/lsa.rb +79 -60
- data/lib/packetgen/header/ospfv2/lsa_header.rb +12 -11
- data/lib/packetgen/header/ospfv2.rb +49 -46
- data/lib/packetgen/header/ospfv3/db_description.rb +20 -22
- data/lib/packetgen/header/ospfv3/hello.rb +17 -16
- data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +22 -20
- data/lib/packetgen/header/ospfv3/ls_ack.rb +7 -8
- data/lib/packetgen/header/ospfv3/ls_request.rb +18 -18
- data/lib/packetgen/header/ospfv3/ls_update.rb +10 -10
- data/lib/packetgen/header/ospfv3/lsa.rb +62 -51
- data/lib/packetgen/header/ospfv3/lsa_header.rb +12 -11
- data/lib/packetgen/header/ospfv3.rb +54 -52
- data/lib/packetgen/header/sctp/chunk.rb +80 -56
- data/lib/packetgen/header/sctp/error.rb +174 -202
- data/lib/packetgen/header/sctp/padded32.rb +3 -3
- data/lib/packetgen/header/sctp/parameter.rb +89 -136
- data/lib/packetgen/header/sctp.rb +19 -8
- data/lib/packetgen/header/snmp.rb +108 -7
- data/lib/packetgen/header/tcp/option.rb +52 -39
- data/lib/packetgen/header/tcp/options.rb +13 -5
- data/lib/packetgen/header/tcp.rb +83 -65
- data/lib/packetgen/header/tftp.rb +31 -25
- data/lib/packetgen/header/udp.rb +21 -19
- data/lib/packetgen/header.rb +23 -18
- data/lib/packetgen/headerable.rb +21 -5
- data/lib/packetgen/inspect.rb +3 -8
- data/lib/packetgen/packet.rb +146 -71
- data/lib/packetgen/pcap.rb +15 -4
- data/lib/packetgen/pcapng/block.rb +20 -18
- data/lib/packetgen/pcapng/epb.rb +13 -15
- data/lib/packetgen/pcapng/file.rb +44 -111
- data/lib/packetgen/pcapng/idb.rb +11 -12
- data/lib/packetgen/pcapng/shb.rb +15 -16
- data/lib/packetgen/pcapng/spb.rb +9 -11
- data/lib/packetgen/pcapng/unknown_block.rb +6 -17
- data/lib/packetgen/pcapng.rb +6 -4
- data/lib/packetgen/pcaprub_wrapper.rb +17 -1
- data/lib/packetgen/proto.rb +5 -1
- data/lib/packetgen/unknown_packet.rb +5 -5
- data/lib/packetgen/utils/arp_spoofer.rb +18 -19
- data/lib/packetgen/utils.rb +4 -3
- data/lib/packetgen/version.rb +1 -1
- data/lib/packetgen.rb +12 -5
- metadata +29 -38
- data/lib/packetgen/types/abstract_tlv.rb +0 -278
- data/lib/packetgen/types/array.rb +0 -287
- data/lib/packetgen/types/cstring.rb +0 -109
- data/lib/packetgen/types/enum.rb +0 -171
- data/lib/packetgen/types/fieldable.rb +0 -66
- data/lib/packetgen/types/fields.rb +0 -622
- data/lib/packetgen/types/int.rb +0 -473
- data/lib/packetgen/types/int_string.rb +0 -102
- data/lib/packetgen/types/length_from.rb +0 -54
- data/lib/packetgen/types/oui.rb +0 -52
- data/lib/packetgen/types/string.rb +0 -97
- data/lib/packetgen/types/tlv.rb +0 -161
- data/lib/packetgen/types.rb +0 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ed11e05d37fb82187dbf1dc0a7dffd1e6c1931ebda0dea904da77f2731a523f8
|
4
|
+
data.tar.gz: e36705786a664ac257d1939a9c67d267a15c52f51e76b02069c923095c0d8852
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 151754f39d113f9dbeb65cda8f62f4e378440aa567c3e528b2d8e93920e70069a55bd26e737c03818a808463a9b3406805dcb8ed92e8b5582fbbfaae7f5d8fd4
|
7
|
+
data.tar.gz: 4f61a79f28f1fe8e5f4cac45b9b8fdc06eeca4ae4a07a567334535b3e8ac7ea5cb85cb6644215656e6c0e7e2d1ba0a58bae1fe66131805af7093742dc5098bdd
|
data/README.md
CHANGED
@@ -1,20 +1,27 @@
|
|
1
1
|
|
2
2
|
[](https://badge.fury.io/rb/packetgen)
|
3
|
-
[](https://github.com/lemontree55/packetgen/actions/workflows/ci.yml)
|
4
|
+
|
4
5
|
# PacketGen
|
5
6
|
|
6
7
|
PacketGen provides simple ways to generate, send and capture network packets.
|
7
8
|
|
8
9
|
## Installation
|
10
|
+
|
9
11
|
PacketGen depends on PcapRub, which needs pcap development files to install. On Debian, you have to do:
|
10
12
|
|
11
|
-
|
13
|
+
```bash
|
14
|
+
sudo apt install libpcap-dev
|
15
|
+
```
|
12
16
|
|
13
17
|
Installation using RubyGems is then easy:
|
14
18
|
|
15
|
-
|
19
|
+
```bash
|
20
|
+
gem install packetgen
|
21
|
+
```
|
16
22
|
|
17
23
|
Or add it to a Gemfile:
|
24
|
+
|
18
25
|
```ruby
|
19
26
|
gem 'packetgen'
|
20
27
|
```
|
@@ -22,6 +29,7 @@ gem 'packetgen'
|
|
22
29
|
## Usage
|
23
30
|
|
24
31
|
### Easily create packets
|
32
|
+
|
25
33
|
```ruby
|
26
34
|
PacketGen.gen('IP') # generate a IP packet object
|
27
35
|
PacketGen.gen('TCP') # generate a TCP over IP packet object
|
@@ -37,6 +45,7 @@ PacketGen.gen('IP').to_s
|
|
37
45
|
```
|
38
46
|
|
39
47
|
### Send packets on wire
|
48
|
+
|
40
49
|
```ruby
|
41
50
|
# send Ethernet packet
|
42
51
|
PacketGen.gen('Eth', src: '00:00:00:00:00:01', dst: '00:00:00:00:00:02').to_w
|
@@ -52,11 +61,13 @@ PacketGen.gen('RadioTap').
|
|
52
61
|
```
|
53
62
|
|
54
63
|
### Parse packets from binary data
|
64
|
+
|
55
65
|
```ruby
|
56
66
|
packet = PacketGen.parse(binary_data)
|
57
67
|
```
|
58
68
|
|
59
69
|
### Capture packets from wire
|
70
|
+
|
60
71
|
```ruby
|
61
72
|
# Capture packets from first network interface, action from a block
|
62
73
|
PacketGen.capture do |packet|
|
@@ -71,6 +82,7 @@ packets = PacketGen.capture(iface: 'eth0', filter: 'ip src 1.1.1.2', max: 1)
|
|
71
82
|
```
|
72
83
|
|
73
84
|
### Easily manipulate packets
|
85
|
+
|
74
86
|
```ruby
|
75
87
|
# access header fields
|
76
88
|
pkt = PacketGen.gen('IP').add('TCP')
|
@@ -96,6 +108,7 @@ pkt2.decapsulate(pkt2.ip) # pkt2 is now inner IP/TCP packet
|
|
96
108
|
```
|
97
109
|
|
98
110
|
### Read/write PcapNG files
|
111
|
+
|
99
112
|
```ruby
|
100
113
|
# read a PcapNG file, containing multiple packets
|
101
114
|
packets = PacketGen.read('file.pcapng')
|
@@ -107,14 +120,16 @@ PacketGen.write('more_packets.pcapng', packets)
|
|
107
120
|
```
|
108
121
|
|
109
122
|
### Add custom header/protocol
|
110
|
-
|
123
|
+
|
124
|
+
PacketGen permits adding your own header classes.
|
125
|
+
|
111
126
|
First, define the new header class. For example:
|
112
127
|
|
113
128
|
```ruby
|
114
129
|
module MyModule
|
115
130
|
class MyHeader < PacketGen::Header::Base
|
116
|
-
|
117
|
-
|
131
|
+
define_attr :field1, BinStruct::Int32
|
132
|
+
define_attr :field2, BinStruct::Int32
|
118
133
|
end
|
119
134
|
end
|
120
135
|
```
|
@@ -135,24 +150,27 @@ PacketGen::Header::IP.bind_header MyModule::MyHeader, protocol: 254
|
|
135
150
|
And use it:
|
136
151
|
|
137
152
|
```ruby
|
138
|
-
pkt = Packet.gen('IP').add('MyHeader', field1: 0x12345678)
|
139
|
-
pkt.
|
153
|
+
pkt = Packet.gen('IP').add('MyHeader', field1: 0x12345678, field2: 0x87654321)
|
154
|
+
pkt.to_w # Send it on wire
|
140
155
|
```
|
141
156
|
|
142
157
|
## Interactive console
|
158
|
+
|
143
159
|
PacketGen provides an interactive console: `pgconsole`.
|
144
160
|
|
145
161
|
In this console, context includes PacketGen module to give direct access to PacketGen
|
146
162
|
classes. A special `config` object gives local network configuration:
|
147
163
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
164
|
+
```text
|
165
|
+
$ pgconsole
|
166
|
+
pg(main)> config
|
167
|
+
=> #<PacketGen::Config:0x00559f27d2afe8
|
168
|
+
@hwaddr="75:74:73:72:71:70",
|
169
|
+
@iface="eth0",
|
170
|
+
@ipaddr="192.168.0.2">
|
171
|
+
pg(main)> packets = capture(max: 5)
|
172
|
+
pg(main)> exit
|
173
|
+
```
|
156
174
|
|
157
175
|
If `pry` gem is installed, it is used as backend for `pgconsole`, else IRB is used.
|
158
176
|
|
@@ -167,20 +185,18 @@ Available plugins (available as gem) are:
|
|
167
185
|
|
168
186
|
## See also
|
169
187
|
|
170
|
-
Wiki: https://github.com/lemontree55/packetgen/wiki
|
188
|
+
Wiki: <https://github.com/lemontree55/packetgen/wiki>
|
171
189
|
|
172
|
-
API documentation: http://www.rubydoc.info/gems/packetgen
|
190
|
+
API documentation: <http://www.rubydoc.info/gems/packetgen>
|
173
191
|
|
174
192
|
## Contributing
|
175
193
|
|
176
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/lemontree55/packetgen
|
194
|
+
Bug reports and pull requests are welcome on GitHub at <https://github.com/lemontree55/packetgen>.
|
177
195
|
|
178
196
|
## License
|
179
197
|
|
180
198
|
MIT License (see [LICENSE](https://github.com/lemontree55/packetgen/blob/master/LICENSE))
|
181
199
|
|
182
200
|
### Other sources
|
183
|
-
All original code maintains its copyright from its original authors and licensing.
|
184
201
|
|
185
|
-
|
186
|
-
but i am the original author.
|
202
|
+
All original code maintains its copyright from its original authors and licensing.
|
data/lib/packetgen/capture.rb
CHANGED
@@ -61,7 +61,7 @@ module PacketGen
|
|
61
61
|
@packets = []
|
62
62
|
@raw_packets = []
|
63
63
|
@timestamps = []
|
64
|
-
set_options
|
64
|
+
set_options(iface, max, timeout, filter, promisc, parse, snaplen, monitor)
|
65
65
|
end
|
66
66
|
|
67
67
|
# Start capture
|
@@ -75,7 +75,7 @@ module PacketGen
|
|
75
75
|
# @author Sylvain Daubert
|
76
76
|
# @author optix2000 - add monitor argument
|
77
77
|
def start(iface: nil, max: nil, timeout: nil, filter: nil, promisc: false, parse: true, snaplen: nil, monitor: nil, &block)
|
78
|
-
set_options
|
78
|
+
set_options(iface, max, timeout, filter, promisc, parse, snaplen, monitor)
|
79
79
|
|
80
80
|
@cap_thread = Thread.new do
|
81
81
|
PCAPRUBWrapper.capture(**capture_args) do |packet|
|
data/lib/packetgen/config.rb
CHANGED
@@ -8,7 +8,7 @@ module PacketGen
|
|
8
8
|
module Deprecation
|
9
9
|
# Default remove version for deprecated classes/methods
|
10
10
|
# @since 3.1.0
|
11
|
-
REMOVE_VERSION = '
|
11
|
+
REMOVE_VERSION = '5.0.0'
|
12
12
|
|
13
13
|
# @private
|
14
14
|
# @param [String] remove_version
|
@@ -29,13 +29,19 @@ module PacketGen
|
|
29
29
|
def self.deprecated(klass, deprecated_method, new_method=nil, klass_method: false, remove_version: REMOVE_VERSION)
|
30
30
|
base_name = "#{klass}#{klass_method ? '.' : '#'}"
|
31
31
|
complete_deprecated_method_name = "#{base_name}#{deprecated_method}"
|
32
|
-
|
32
|
+
unless new_method.nil?
|
33
|
+
complete_new_method_name = if %w[# .].any? { |punct| new_method.include?(punct) }
|
34
|
+
new_method
|
35
|
+
else
|
36
|
+
"#{base_name}#{new_method}"
|
37
|
+
end
|
38
|
+
end
|
33
39
|
|
34
40
|
file, line = caller(2..2).first.split(':')[0, 2]
|
35
|
-
message =
|
41
|
+
message = "#{file}:#{line}: #{complete_deprecated_method_name} is deprecated"
|
36
42
|
message << " in favor of #{complete_new_method_name}" unless new_method.nil?
|
37
43
|
message << '. ' << self.removed(remove_version)
|
38
|
-
warn
|
44
|
+
warn(message)
|
39
45
|
end
|
40
46
|
|
41
47
|
# Warn when using a deprecated method
|
@@ -46,10 +52,10 @@ module PacketGen
|
|
46
52
|
# @since 3.1.0
|
47
53
|
def self.deprecated_class(klass, new_klass=nil, remove_version: REMOVE_VERSION)
|
48
54
|
file, line = caller(2..2).first.split(':')[0, 2]
|
49
|
-
message =
|
55
|
+
message = "#{file}:#{line}: #{klass} is deprecated"
|
50
56
|
message << " in favor of #{new_klass}" unless new_klass.nil?
|
51
57
|
message << '. ' << self.removed(remove_version)
|
52
|
-
warn
|
58
|
+
warn(message)
|
53
59
|
end
|
54
60
|
|
55
61
|
# Warn when using a deprecated method's option
|
@@ -64,9 +70,9 @@ module PacketGen
|
|
64
70
|
def self.deprecated_option(klass, method, option, klass_method: false, remove_version: REMOVE_VERSION)
|
65
71
|
base_name = "#{klass}#{klass_method ? '.' : '#'}"
|
66
72
|
method_name = "#{base_name}#{method}"
|
67
|
-
message =
|
73
|
+
message = "option #{option} is deprecated for method #{method_name}. "
|
68
74
|
message << self.removed(remove_version)
|
69
|
-
warn
|
75
|
+
warn(message)
|
70
76
|
end
|
71
77
|
end
|
72
78
|
end
|
data/lib/packetgen/header/arp.rb
CHANGED
@@ -9,9 +9,9 @@
|
|
9
9
|
module PacketGen
|
10
10
|
module Header
|
11
11
|
# An ARP header consists of:
|
12
|
-
# * a hardware type ({#hrd} or {#htype}) field (
|
12
|
+
# * a hardware type ({#hrd} or {#htype}) field (+BinStruct::Int16+),
|
13
13
|
# * a protocol type ({#pro} or {#ptype}) field (+Int16+),
|
14
|
-
# * a hardware address length ({#hln} or {#hlen}) field (
|
14
|
+
# * a hardware address length ({#hln} or {#hlen}) field (+BinStruct::Int8+),
|
15
15
|
# * a protocol address length ({#pln} or {#plen}) field (+Int8+),
|
16
16
|
# * a {#opcode} (or {#op}) field (+Int16+),
|
17
17
|
# * a source hardware address ({#sha} or {#src_mac}) field ({Eth::MacAddr}),
|
@@ -20,55 +20,55 @@ module PacketGen
|
|
20
20
|
# * a target protocol address ({#tpa} or {#dst_ip}) field (+IP::Addr+),
|
21
21
|
# * and a {#body}.
|
22
22
|
#
|
23
|
-
#
|
23
|
+
# @example Create a ARP header
|
24
24
|
# # standalone
|
25
25
|
# arp = PacketGen::Header::ARP.new
|
26
26
|
# # in a packet
|
27
27
|
# pkt = PacketGen.gen('Eth').add('ARP')
|
28
28
|
# # access to ARP header
|
29
|
-
# pkt.arp # =>
|
29
|
+
# pkt.arp.protocol_name # => "ARP"
|
30
30
|
#
|
31
31
|
# @author Sylvain Daubert
|
32
32
|
class ARP < Base
|
33
33
|
# @!attribute hrd
|
34
34
|
# 16-bit hardware protocol type
|
35
35
|
# # @return [Integer]
|
36
|
-
|
36
|
+
define_attr :hrd, BinStruct::Int16, default: 1
|
37
37
|
# @!attribute pro
|
38
38
|
# 16-bit internet protocol type
|
39
39
|
# # @return [Integer]
|
40
|
-
|
40
|
+
define_attr :pro, BinStruct::Int16, default: 0x800
|
41
41
|
# @!attribute hln
|
42
42
|
# 8-bit hardware address length
|
43
43
|
# # @return [Integer]
|
44
|
-
|
44
|
+
define_attr :hln, BinStruct::Int8, default: 6
|
45
45
|
# @!attribute pln
|
46
46
|
# 8-bit internet address length
|
47
47
|
# # @return [Integer]
|
48
|
-
|
48
|
+
define_attr :pln, BinStruct::Int8, default: 4
|
49
49
|
# @!attribute op
|
50
50
|
# 16-bit operation code
|
51
51
|
# # @return [Integer]
|
52
|
-
|
52
|
+
define_attr :op, BinStruct::Int16Enum, enum: { 'request' => 1, 'reply' => 2 }
|
53
53
|
# @!attribute sha
|
54
54
|
# source hardware address
|
55
55
|
# @return [Eth::MacAddr]
|
56
|
-
|
56
|
+
define_attr :sha, Eth::MacAddr
|
57
57
|
# @!attribute spa
|
58
58
|
# source protocol address
|
59
59
|
# @return [IP::Addr]
|
60
|
-
|
60
|
+
define_attr :spa, IP::Addr
|
61
61
|
# @!attribute tha
|
62
62
|
# target hardware address
|
63
63
|
# @return [Eth::MacAddr]
|
64
|
-
|
64
|
+
define_attr :tha, Eth::MacAddr
|
65
65
|
# @!attribute tpa
|
66
66
|
# target protocol address
|
67
67
|
# @return [IP::Addr]
|
68
|
-
|
68
|
+
define_attr :tpa, IP::Addr
|
69
69
|
# @!attribute body
|
70
|
-
# @return [
|
71
|
-
|
70
|
+
# @return [BinStruct::String,Header::Base]
|
71
|
+
define_attr :body, BinStruct::String
|
72
72
|
|
73
73
|
# @param [Hash] options
|
74
74
|
# @option options [Integer] :hrd network protocol type (default: 1)
|
@@ -122,8 +122,7 @@ module PacketGen
|
|
122
122
|
|
123
123
|
private
|
124
124
|
|
125
|
-
|
126
|
-
def handle_options(options)
|
125
|
+
def handle_options(options)
|
127
126
|
options[:hrd] ||= options[:htype]
|
128
127
|
options[:pro] ||= options[:ptype]
|
129
128
|
options[:hln] ||= options[:hlen]
|
@@ -134,7 +133,7 @@ module PacketGen
|
|
134
133
|
options[:tha] ||= options[:dst_mac]
|
135
134
|
options[:tpa] ||= options[:dst_ip]
|
136
135
|
end
|
137
|
-
# rubocop:enable Metrics
|
136
|
+
# rubocop:enable Metrics
|
138
137
|
|
139
138
|
def invert_addresses
|
140
139
|
self.spa, self.tpa = self.tpa, self.spa
|
@@ -21,7 +21,7 @@ module PacketGen
|
|
21
21
|
include Headerable
|
22
22
|
|
23
23
|
class << self
|
24
|
-
# Define some methods from given ASN.1
|
24
|
+
# Define some methods from given ASN.1 attributes to mimic {Base} attributes
|
25
25
|
# @param [Array<Symbol>] attributes
|
26
26
|
# @return [void]
|
27
27
|
def define_attributes(*attributes)
|
@@ -32,6 +32,7 @@ module PacketGen
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
+
# @return [Hash]
|
35
36
|
def known_headers
|
36
37
|
@known_headers ||= {}.freeze
|
37
38
|
end
|
@@ -13,28 +13,30 @@ module PacketGen
|
|
13
13
|
# * +#calc_checksum+, which computes header checksum,
|
14
14
|
# * +#calc_length+, which computes header length,
|
15
15
|
# * {#parse?},
|
16
|
-
# * +#reply!+, which inverts needed
|
16
|
+
# * +#reply!+, which inverts needed attributes to forge a response.
|
17
|
+
# {Base} class defines {.bind} method, to bind headers to outer ones.
|
17
18
|
# @author Sylvain Daubert
|
18
|
-
|
19
|
+
# @author LemonTree55
|
20
|
+
class Base < BinStruct::Struct
|
19
21
|
include Headerable
|
20
22
|
|
21
23
|
# @api private
|
22
24
|
# Simple class to handle a header association
|
23
|
-
class Binding < Struct.new(:key, :value)
|
25
|
+
class Binding < ::Struct.new(:key, :value)
|
24
26
|
# Check +fields+ responds to binding
|
25
|
-
# @param [
|
27
|
+
# @param [BinStruct::Struct] fields
|
26
28
|
# @return [Boolean]
|
27
29
|
def check?(fields)
|
28
30
|
case self[:value]
|
29
31
|
when Proc
|
30
|
-
self[:value].call
|
32
|
+
self[:value].call(fields.send(self[:key]))
|
31
33
|
else
|
32
34
|
fields.send(self[:key]) == self[:value]
|
33
35
|
end
|
34
36
|
end
|
35
37
|
|
36
38
|
# Set +fields+ field to binding value
|
37
|
-
# @param [
|
39
|
+
# @param [BinStruct::Struct] fields
|
38
40
|
# @return [void]
|
39
41
|
def set(fields)
|
40
42
|
case self[:value]
|
@@ -54,7 +56,7 @@ module PacketGen
|
|
54
56
|
# @api private
|
55
57
|
# Class to handle a header association from procs
|
56
58
|
class ProcBinding
|
57
|
-
# @param [Array
|
59
|
+
# @param [Array(Proc,Proc)] procs first proc is used to set fields, second proc is
|
58
60
|
# used to check binding
|
59
61
|
def initialize(procs)
|
60
62
|
@set = procs.shift
|
@@ -62,14 +64,14 @@ module PacketGen
|
|
62
64
|
end
|
63
65
|
|
64
66
|
# Check +fields+ responds to binding
|
65
|
-
# @param [
|
67
|
+
# @param [BinStruct::Struct] fields
|
66
68
|
# @return [Boolean]
|
67
69
|
def check?(fields)
|
68
70
|
@check.call(fields)
|
69
71
|
end
|
70
72
|
|
71
73
|
# Set +fields+ field to binding value
|
72
|
-
# @param [
|
74
|
+
# @param [BinStruct::Struct] fields
|
73
75
|
# @return [void]
|
74
76
|
def set(fields)
|
75
77
|
@set.call(fields)
|
@@ -77,11 +79,11 @@ module PacketGen
|
|
77
79
|
end
|
78
80
|
|
79
81
|
# @api private
|
80
|
-
# Class to handle header associations
|
82
|
+
# Class to handle a set of header associations ({Binding} or/and {ProcBinding})
|
81
83
|
class Bindings
|
82
84
|
include Enumerable
|
83
85
|
|
84
|
-
# @return [Array<Binding>]
|
86
|
+
# @return [Array<Binding,ProcBinding>]
|
85
87
|
attr_accessor :bindings
|
86
88
|
|
87
89
|
def initialize
|
@@ -92,7 +94,7 @@ module PacketGen
|
|
92
94
|
@bindings << []
|
93
95
|
end
|
94
96
|
|
95
|
-
# @param [
|
97
|
+
# @param [Binding,ProcBinding] arg
|
96
98
|
# @return [Bindings] self
|
97
99
|
def <<(arg)
|
98
100
|
@bindings.last << arg
|
@@ -100,6 +102,7 @@ module PacketGen
|
|
100
102
|
|
101
103
|
# each iterator
|
102
104
|
# @return [void]
|
105
|
+
# @yieldparam [Binding,ProcBinding] binding
|
103
106
|
def each(&block)
|
104
107
|
@bindings.each(&block)
|
105
108
|
end
|
@@ -109,7 +112,7 @@ module PacketGen
|
|
109
112
|
@bindings.empty?
|
110
113
|
end
|
111
114
|
|
112
|
-
# Return
|
115
|
+
# Return bindings as a hash.
|
113
116
|
# @return [Hash]
|
114
117
|
def to_h
|
115
118
|
hsh = {}
|
@@ -120,22 +123,22 @@ module PacketGen
|
|
120
123
|
end
|
121
124
|
|
122
125
|
# Check +fields+ responds to set of bindings
|
123
|
-
# @param [
|
126
|
+
# @param [BinStruct::Struct] fields
|
124
127
|
# @return [Boolean]
|
125
128
|
def check?(fields)
|
126
129
|
@bindings.any? { |group| group.all? { |binding| binding.check?(fields) } }
|
127
130
|
end
|
128
131
|
|
129
132
|
# Set +fields+ to bindings value
|
130
|
-
# @param [
|
133
|
+
# @param [BinStruct::Struct] fields
|
131
134
|
# @return [void]
|
132
135
|
def set(fields)
|
133
|
-
@bindings.first.each { |b| b.set
|
136
|
+
@bindings.first.each { |b| b.set(fields) }
|
134
137
|
end
|
135
138
|
end
|
136
139
|
|
137
140
|
# @private
|
138
|
-
# On
|
141
|
+
# On inheritance, create +@known_header+ class variable
|
139
142
|
# @param [Class] klass
|
140
143
|
# @return [void]
|
141
144
|
def self.inherited(klass)
|
@@ -146,12 +149,12 @@ module PacketGen
|
|
146
149
|
class << self
|
147
150
|
# @api private
|
148
151
|
# Get known headers
|
149
|
-
# @return [Hash
|
152
|
+
# @return [Hash{Headerable => Bindings}]
|
150
153
|
attr_reader :known_headers
|
151
154
|
|
152
155
|
# Bind a upper header to current one.
|
153
156
|
# @param [Class] header_klass header class to bind to current class
|
154
|
-
# @param [Hash] args current class
|
157
|
+
# @param [Hash] args current class attributes and their value when +header_klass+
|
155
158
|
# is embedded in current class.
|
156
159
|
#
|
157
160
|
# Given value may be a lambda, whose alone argument is the value extracted
|
@@ -163,30 +166,29 @@ module PacketGen
|
|
163
166
|
# non-trivial checks should be made.
|
164
167
|
# @return [void]
|
165
168
|
# @example Basic examples
|
166
|
-
# # Bind
|
167
|
-
#
|
168
|
-
# # Bind
|
169
|
-
# # and
|
170
|
-
#
|
171
|
-
#
|
169
|
+
# # Bind TCP to IP when protocol attribute from IP has a value of 66
|
170
|
+
# PacketGen::Header::IP.bind PacketGen::Header::TCP, protocol: 66
|
171
|
+
# # Bind UDP to IP when protocol from IP has a value of 177
|
172
|
+
# # and tos has value 43 or 44
|
173
|
+
# PacketGen::Header::IP .bind PacketGen::Header::UDP, protocol: 177, tos: 43
|
174
|
+
# PacketGen::Header::IP .bind PacketGen::Header::UDP, protocol: 177, tos: 44
|
172
175
|
# @example Defining a binding on a field using a lambda.
|
173
|
-
# # Bind
|
174
|
-
# # greater or equal to 44. When adding a
|
176
|
+
# # Bind DHCP to Eth when ethertype from Eth has a value
|
177
|
+
# # greater or equal to 44. When adding a DHCP to a Eth
|
175
178
|
# # with Packet#add, force value to 44.
|
176
|
-
#
|
179
|
+
# PacketGen::Header::Eth.bind PacketGen::Header::DHCP, ethertype: ->(v) { v.nil? ? 44 : v >= 44 }
|
177
180
|
# @example Defining a binding using procs key
|
178
|
-
# # Bind
|
179
|
-
# # and first two bytes of
|
180
|
-
# # When adding a
|
181
|
-
#
|
182
|
-
#
|
181
|
+
# # Bind IPv6 to IP when protocol from IP has a value of 255
|
182
|
+
# # and first two bytes of IP's body are 0x6000.
|
183
|
+
# # When adding a IPv6 to a IP with Packet#add, force value to 255.
|
184
|
+
# PacketGen::Header::IP.bind PacketGen::Header::IPv6, procs: [->(hdr) { hdr.protocol = 255 },
|
185
|
+
# ->(hdr) { hdr.protocol == 255 && hdr.body[0..1] == "\x60\x00" }]
|
183
186
|
# @since 2.7.0
|
184
187
|
def bind(header_klass, args={})
|
185
|
-
|
188
|
+
bindings = @known_headers[header_klass]
|
189
|
+
if bindings.nil?
|
186
190
|
bindings = Bindings.new
|
187
191
|
@known_headers[header_klass] = bindings
|
188
|
-
else
|
189
|
-
bindings = @known_headers[header_klass]
|
190
192
|
end
|
191
193
|
bindings.new_set
|
192
194
|
args.each do |key, value|
|
@@ -213,7 +215,7 @@ module PacketGen
|
|
213
215
|
end
|
214
216
|
end
|
215
217
|
|
216
|
-
# @see
|
218
|
+
# @see BinStruct::Struct#initialize
|
217
219
|
def initialize(options={})
|
218
220
|
@packet = options.delete(:packet) if options.key?(:packet)
|
219
221
|
super
|
@@ -222,7 +224,7 @@ module PacketGen
|
|
222
224
|
# @api private
|
223
225
|
# Get +header+ id in {Packet#headers} array
|
224
226
|
# @param [Header] header
|
225
|
-
# @return [Integer]
|
227
|
+
# @return [Integer] header id
|
226
228
|
# @raise [FormatError] +header+ not in a packet
|
227
229
|
def header_id(header)
|
228
230
|
raise FormatError, "header of type #{header.class} not in a packet" if packet.nil?
|
@@ -242,13 +244,13 @@ module PacketGen
|
|
242
244
|
def ip_header(header)
|
243
245
|
hid = header_id(header)
|
244
246
|
iph = packet.headers[0...hid].reverse.find { |h| h.is_a?(IP) || h.is_a?(IPv6) }
|
245
|
-
raise FormatError, 'no IP
|
247
|
+
raise FormatError, 'no IP nor IPv6 header in packet' if iph.nil?
|
246
248
|
|
247
249
|
iph
|
248
250
|
end
|
249
251
|
|
250
252
|
# @api private
|
251
|
-
# Get link layer header from given header
|
253
|
+
# Get link layer ({Eth} or {Dot11}) header from given header
|
252
254
|
# @param [Header] header
|
253
255
|
# @return [Header]
|
254
256
|
# @raise [FormatError] no link layer header in packet
|