packetgen 2.8.7 → 3.0.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/.rubocop.yml +0 -1
- data/README.md +5 -4
- data/lib/packetgen.rb +6 -12
- data/lib/packetgen/capture.rb +43 -39
- data/lib/packetgen/config.rb +0 -1
- data/lib/packetgen/deprecation.rb +1 -1
- data/lib/packetgen/header.rb +9 -9
- data/lib/packetgen/header/asn1_base.rb +10 -10
- data/lib/packetgen/header/base.rb +42 -101
- data/lib/packetgen/header/dhcp/option.rb +5 -11
- data/lib/packetgen/header/dhcpv6/duid.rb +2 -0
- data/lib/packetgen/header/dhcpv6/option.rb +2 -19
- data/lib/packetgen/header/dhcpv6/options.rb +7 -0
- data/lib/packetgen/header/dns.rb +5 -23
- data/lib/packetgen/header/dns/name.rb +1 -0
- data/lib/packetgen/header/dns/qdsection.rb +1 -0
- data/lib/packetgen/header/dns/question.rb +3 -7
- data/lib/packetgen/header/dns/rr.rb +3 -0
- data/lib/packetgen/header/dns/rrsection.rb +1 -0
- data/lib/packetgen/header/dot11.rb +1 -17
- data/lib/packetgen/header/dot1x.rb +1 -0
- data/lib/packetgen/header/eap.rb +4 -7
- data/lib/packetgen/header/eth.rb +2 -0
- data/lib/packetgen/header/http/headers.rb +3 -0
- data/lib/packetgen/header/http/request.rb +5 -4
- data/lib/packetgen/header/http/response.rb +5 -4
- data/lib/packetgen/header/icmp.rb +6 -0
- data/lib/packetgen/header/icmpv6.rb +6 -0
- data/lib/packetgen/header/igmpv3/mq.rb +2 -0
- data/lib/packetgen/header/ip.rb +32 -30
- data/lib/packetgen/header/ip/addr.rb +1 -0
- data/lib/packetgen/header/ip/option.rb +23 -20
- data/lib/packetgen/header/ip/options.rb +11 -24
- data/lib/packetgen/header/ipv6.rb +45 -34
- data/lib/packetgen/header/ipv6/addr.rb +2 -0
- data/lib/packetgen/header/ipv6/hop_by_hop.rb +7 -31
- data/lib/packetgen/header/mdns.rb +1 -0
- data/lib/packetgen/header/mldv2/mlq.rb +2 -0
- data/lib/packetgen/header/ospfv2/lsa.rb +15 -25
- data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +1 -1
- data/lib/packetgen/header/ospfv3/lsa.rb +8 -25
- data/lib/packetgen/header/snmp.rb +2 -0
- data/lib/packetgen/header/tcp.rb +23 -2
- data/lib/packetgen/header/tcp/option.rb +51 -52
- data/lib/packetgen/header/tcp/options.rb +17 -52
- data/lib/packetgen/header/tftp.rb +3 -0
- data/lib/packetgen/header/udp.rb +8 -0
- data/lib/packetgen/packet.rb +119 -102
- data/lib/packetgen/pcapng/block.rb +4 -10
- data/lib/packetgen/pcapng/epb.rb +4 -4
- data/lib/packetgen/pcapng/file.rb +7 -3
- data/lib/packetgen/pcapng/idb.rb +2 -2
- data/lib/packetgen/pcapng/shb.rb +3 -3
- data/lib/packetgen/pcapng/spb.rb +1 -8
- data/lib/packetgen/pcapng/unknown_block.rb +0 -7
- data/lib/packetgen/types.rb +1 -0
- data/lib/packetgen/types/array.rb +73 -71
- data/lib/packetgen/types/cstring.rb +1 -1
- data/lib/packetgen/types/enum.rb +3 -3
- data/lib/packetgen/types/fields.rb +66 -106
- data/lib/packetgen/types/int.rb +9 -5
- data/lib/packetgen/types/length_from.rb +45 -0
- data/lib/packetgen/types/oui.rb +2 -0
- data/lib/packetgen/types/string.rb +10 -16
- data/lib/packetgen/types/tlv.rb +7 -15
- data/lib/packetgen/utils.rb +8 -8
- data/lib/packetgen/utils/arp_spoofer.rb +1 -2
- data/lib/packetgen/version.rb +1 -1
- metadata +3 -21
- data/lib/packetgen/header/crypto.rb +0 -62
- data/lib/packetgen/header/esp.rb +0 -413
- data/lib/packetgen/header/ike.rb +0 -243
- data/lib/packetgen/header/ike/auth.rb +0 -165
- data/lib/packetgen/header/ike/cert.rb +0 -76
- data/lib/packetgen/header/ike/certreq.rb +0 -66
- data/lib/packetgen/header/ike/id.rb +0 -99
- data/lib/packetgen/header/ike/ke.rb +0 -79
- data/lib/packetgen/header/ike/nonce.rb +0 -40
- data/lib/packetgen/header/ike/notify.rb +0 -176
- data/lib/packetgen/header/ike/payload.rb +0 -315
- data/lib/packetgen/header/ike/sa.rb +0 -561
- data/lib/packetgen/header/ike/sk.rb +0 -261
- data/lib/packetgen/header/ike/ts.rb +0 -270
- data/lib/packetgen/header/ike/vendor_id.rb +0 -39
- data/lib/packetgen/header/netbios.rb +0 -20
- data/lib/packetgen/header/netbios/datagram.rb +0 -105
- data/lib/packetgen/header/netbios/name.rb +0 -67
- data/lib/packetgen/header/netbios/session.rb +0 -64
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 072c0bb14448db25532a552f9b8a5c83b2363d7ccb3692d478f3224a8cc34807
|
4
|
+
data.tar.gz: b2b857e9793aa1dabf0a89562958187087afabb10318cf947d9c2ce12696c39d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d5bb7c964881ae0f2df1845d82b449cf1a80c25432c740dc1e7ce6436b4323e03586d40760939d554daba0080a15d776cbe8b7fed04c07983a77aaad9c2e0e3d
|
7
|
+
data.tar.gz: 9a2d0bd3355ec82bb40c0ed3a4377852314e74bb6f3479142810d637ca5f189279c7d8f3ae0bc59eea6ffc8f91d19264a2d0ced8d39c49cfc91a9d004d9bbe47
|
data/.rubocop.yml
CHANGED
data/README.md
CHANGED
@@ -114,8 +114,8 @@ First, define the new header class. For example:
|
|
114
114
|
```ruby
|
115
115
|
module MyModule
|
116
116
|
class MyHeader < PacketGen::Header::Base
|
117
|
-
define_field :field1, PacketGen::Types::Int32
|
118
|
-
define_field :field2, PacketGen::Types::Int32
|
117
|
+
define_field :field1, PacketGen::Types::Int32
|
118
|
+
define_field :field2, PacketGen::Types::Int32
|
119
119
|
end
|
120
120
|
end
|
121
121
|
```
|
@@ -161,8 +161,9 @@ If `pry` gem is installed, it is used as backend for `pgconsole`, else IRB is us
|
|
161
161
|
|
162
162
|
PacketGen provides a plugin system (see [wiki](https://github.com/sdaubert/packetgen/wiki/Create-Custom-Protocol)).
|
163
163
|
|
164
|
-
|
164
|
+
Available plugins (available as gem) are:
|
165
165
|
|
166
|
+
* [packetgen-plugin-ipsec](https://github.com/sdaubert/packetgen-plugin-ipsec): add support for ESP and IKEv2 protocols. Before PacketGen3, these protocols were included in packetgen.
|
166
167
|
* [packetgen-plugin-smb](https://github.com/sdaubert/packetgen-plugin-smb): add (limited) support for SMB protocol suite.
|
167
168
|
|
168
169
|
## See also
|
@@ -173,7 +174,7 @@ API documentation: http://www.rubydoc.info/gems/packetgen
|
|
173
174
|
|
174
175
|
## Contributing
|
175
176
|
|
176
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/sdaubert/packetgen
|
177
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/sdaubert/packetgen.
|
177
178
|
|
178
179
|
## License
|
179
180
|
|
data/lib/packetgen.rb
CHANGED
@@ -7,6 +7,7 @@
|
|
7
7
|
# frozen_string_literal: true
|
8
8
|
|
9
9
|
require 'packetgen/version'
|
10
|
+
require 'interfacez'
|
10
11
|
|
11
12
|
# PacketGen is a network packet generator and analyzor.
|
12
13
|
# @author Sylvain Daubert
|
@@ -40,11 +41,12 @@ module PacketGen
|
|
40
41
|
end
|
41
42
|
|
42
43
|
# Shortcut for {Packet.capture}
|
43
|
-
#
|
44
|
+
# Same arguments as {Capture#initialize}
|
45
|
+
# @see Capture#initialize
|
44
46
|
# @yieldparam [Packet] packet
|
45
47
|
# @return [Array<Packet>]
|
46
|
-
def self.capture(
|
47
|
-
Packet.capture(
|
48
|
+
def self.capture(**kwargs)
|
49
|
+
Packet.capture(kwargs) { |packet| yield packet if block_given? }
|
48
50
|
end
|
49
51
|
|
50
52
|
# Shortcut for {Packet.read}
|
@@ -72,15 +74,7 @@ module PacketGen
|
|
72
74
|
# Get default network interface (ie. first non-loopback declared interface)
|
73
75
|
# @return [String]
|
74
76
|
def self.default_iface
|
75
|
-
|
76
|
-
|
77
|
-
ipaddr = `ip addr`.split("\n")
|
78
|
-
@default_iface = ipaddr.each do |line|
|
79
|
-
m = line.match(/^\d+: (\w+\d+):/)
|
80
|
-
next if m.nil?
|
81
|
-
next if m[1].start_with? 'lo'
|
82
|
-
break m[1]
|
83
|
-
end
|
77
|
+
Interfacez.default
|
84
78
|
end
|
85
79
|
|
86
80
|
# Shortcut to get a header class
|
data/lib/packetgen/capture.rb
CHANGED
@@ -5,8 +5,6 @@
|
|
5
5
|
|
6
6
|
# frozen_string_literal: true
|
7
7
|
|
8
|
-
require 'interfacez'
|
9
|
-
|
10
8
|
module PacketGen
|
11
9
|
# Capture packets from wire
|
12
10
|
# @author Sylvain Daubert
|
@@ -15,6 +13,12 @@ module PacketGen
|
|
15
13
|
# Default snaplen to use if :snaplen option not defined.
|
16
14
|
DEFAULT_SNAPLEN = 0xffff
|
17
15
|
|
16
|
+
private
|
17
|
+
|
18
|
+
attr_reader :filter, :cap_thread
|
19
|
+
|
20
|
+
public
|
21
|
+
|
18
22
|
# Get captured packets.
|
19
23
|
# @return [Array<Packets>]
|
20
24
|
attr_reader :packets
|
@@ -27,53 +31,53 @@ module PacketGen
|
|
27
31
|
# @return [String]
|
28
32
|
attr_reader :iface
|
29
33
|
|
30
|
-
# @param [
|
31
|
-
# @option options [String] :iface interface on which capture
|
34
|
+
# @param [String] iface interface on which capture
|
32
35
|
# packets on. Default: Use default interface lookup. If no interface found,
|
33
36
|
# use loopback one.
|
34
|
-
# @
|
35
|
-
# @
|
37
|
+
# @param [Integer] max maximum number of packets to capture.
|
38
|
+
# @param [Integer] timeout maximum number of seconds before end
|
36
39
|
# of capture. Default: +nil+ (no timeout)
|
37
|
-
# @
|
38
|
-
# @
|
39
|
-
# @
|
40
|
+
# @param [String] filter bpf filter
|
41
|
+
# @param [Boolean] promisc (default: +false+)
|
42
|
+
# @param [Boolean] parse parse raw data to generate packets before
|
40
43
|
# yielding. Default: +true+
|
41
|
-
# @
|
44
|
+
# @param [Integer] snaplen maximum number of bytes to capture for
|
42
45
|
# each packet.
|
43
46
|
# @since 2.0.0 remove old 1.x API
|
44
|
-
|
45
|
-
|
47
|
+
# @since 3.0.0 arguments are kwargs and nor more a hash
|
48
|
+
def initialize(iface: nil, max: nil, timeout: nil, filter: nil, promisc: false, parse: true, snaplen: DEFAULT_SNAPLEN)
|
49
|
+
@iface = iface || Interfacez.default || Interfacez.loopback
|
46
50
|
|
47
51
|
@packets = []
|
48
52
|
@raw_packets = []
|
49
|
-
|
50
|
-
@snaplen = DEFAULT_SNAPLEN
|
51
|
-
@parse = true
|
52
|
-
set_options options
|
53
|
+
set_options iface, max, timeout, filter, promisc, parse, snaplen
|
53
54
|
end
|
54
55
|
|
55
56
|
# Start capture
|
56
|
-
# @
|
57
|
+
# @see {#initialize} for parameters
|
57
58
|
# @yieldparam [Packet,String] packet if a block is given, yield each
|
58
59
|
# captured packet (Packet or raw data String, depending on +:parse+ option)
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
60
|
+
# @since 3.0.0 arguments are kwargs and nor more a hash
|
61
|
+
def start(iface: nil, max: nil, timeout: nil, filter: nil, promisc: false, parse: true, snaplen: DEFAULT_SNAPLEN)
|
62
|
+
set_options iface, max, timeout, filter, promisc, parse, snaplen
|
63
|
+
|
64
|
+
pcap = PCAPRUB::Pcap.open_live(self.iface, @snaplen, @promisc, 1)
|
65
|
+
set_filter_on pcap
|
66
|
+
|
63
67
|
@cap_thread = Thread.new do
|
64
|
-
|
65
|
-
|
68
|
+
pcap.each do |packet_data|
|
69
|
+
raw_packets << packet_data
|
66
70
|
if @parse
|
67
71
|
packet = Packet.parse(packet_data)
|
68
|
-
|
72
|
+
packets << packet
|
69
73
|
yield packet if block_given?
|
70
74
|
elsif block_given?
|
71
75
|
yield packet_data
|
72
76
|
end
|
73
|
-
break if @max &&
|
77
|
+
break if defined?(@max) && (raw_packets.size >= @max)
|
74
78
|
end
|
75
79
|
end
|
76
|
-
|
80
|
+
cap_thread.join(@timeout)
|
77
81
|
end
|
78
82
|
|
79
83
|
# Stop capture. Should be used from another thread, as {#start} blocks.
|
@@ -82,25 +86,25 @@ module PacketGen
|
|
82
86
|
# has been made to make Capture nor PacketGen thread-safe.
|
83
87
|
# @return [void]
|
84
88
|
def stop
|
85
|
-
|
89
|
+
cap_thread.kill
|
86
90
|
end
|
87
91
|
|
88
92
|
private
|
89
93
|
|
90
|
-
def set_options(
|
91
|
-
@max =
|
92
|
-
@filter =
|
93
|
-
@timeout =
|
94
|
-
@promisc =
|
95
|
-
@snaplen =
|
96
|
-
@parse =
|
97
|
-
@iface =
|
94
|
+
def set_options(iface, max, timeout, filter, promisc, parse, snaplen)
|
95
|
+
@max = max if max
|
96
|
+
@filter = filter unless filter.nil?
|
97
|
+
@timeout = timeout unless timeout.nil?
|
98
|
+
@promisc = promisc unless promisc.nil?
|
99
|
+
@snaplen = snaplen unless snaplen.nil?
|
100
|
+
@parse = parse unless parse.nil?
|
101
|
+
@iface = iface unless iface.nil?
|
98
102
|
end
|
99
103
|
|
100
|
-
def
|
101
|
-
return if
|
102
|
-
|
103
|
-
|
104
|
+
def set_filter_on(pcap)
|
105
|
+
return if filter.nil? || filter.empty?
|
106
|
+
|
107
|
+
pcap.setfilter filter
|
104
108
|
end
|
105
109
|
end
|
106
110
|
end
|
data/lib/packetgen/config.rb
CHANGED
@@ -4,7 +4,7 @@ module PacketGen
|
|
4
4
|
# @author Sylvain Daubert
|
5
5
|
# @api private
|
6
6
|
module Deprecation
|
7
|
-
def self.deprecated(klass, deprecated_method, new_method=nil, klass_method: false, remove_version: '
|
7
|
+
def self.deprecated(klass, deprecated_method, new_method=nil, klass_method: false, remove_version: '4.0.0')
|
8
8
|
separator = klass_method ? '.' : '#'
|
9
9
|
base_name = klass.to_s + separator
|
10
10
|
complete_deprecated_method_name = base_name + deprecated_method.to_s
|
data/lib/packetgen/header.rb
CHANGED
@@ -7,9 +7,12 @@
|
|
7
7
|
# frozen_string_literal: true
|
8
8
|
|
9
9
|
module PacketGen
|
10
|
-
# Namespace for protocol header classes
|
10
|
+
# Namespace for protocol header classes.
|
11
|
+
#
|
12
|
+
# This namespace handles all buitlin headers, such as {IP} or {TCP}.
|
13
|
+
#
|
11
14
|
# == Add a foreign header class
|
12
|
-
#
|
15
|
+
# PacketGen permits adding you own header classes.
|
13
16
|
# First, define the new header class. By example:
|
14
17
|
# module MyModule
|
15
18
|
# class MyHeader < PacketGen::Header::Base
|
@@ -40,7 +43,8 @@ module PacketGen
|
|
40
43
|
# List all available headers.
|
41
44
|
# @return [Array<Class>]
|
42
45
|
def all
|
43
|
-
return @header_classes if @header_classes
|
46
|
+
return @header_classes if defined?(@header_classes) && @header_classes
|
47
|
+
|
44
48
|
@header_classes = @added_header_classes.values
|
45
49
|
end
|
46
50
|
alias list all
|
@@ -51,7 +55,7 @@ module PacketGen
|
|
51
55
|
# @return [void]
|
52
56
|
# @since 1.1.0
|
53
57
|
def add_class(klass)
|
54
|
-
protocol_name = klass.
|
58
|
+
protocol_name = klass.protocol_name
|
55
59
|
@added_header_classes[protocol_name] = klass
|
56
60
|
@header_classes = nil
|
57
61
|
end
|
@@ -62,7 +66,7 @@ module PacketGen
|
|
62
66
|
# @return [void]
|
63
67
|
# @since 1.1.0
|
64
68
|
def remove_class(klass)
|
65
|
-
protocol_name = klass.
|
69
|
+
protocol_name = klass.protocol_name
|
66
70
|
@added_header_classes.delete protocol_name
|
67
71
|
@header_classes = nil
|
68
72
|
end
|
@@ -82,7 +86,6 @@ module PacketGen
|
|
82
86
|
end
|
83
87
|
end
|
84
88
|
|
85
|
-
require_relative 'header/crypto'
|
86
89
|
require_relative 'header/base'
|
87
90
|
require_relative 'header/eth'
|
88
91
|
require_relative 'header/dot11'
|
@@ -98,8 +101,6 @@ require_relative 'header/gre'
|
|
98
101
|
require_relative 'header/udp'
|
99
102
|
require_relative 'header/tcp'
|
100
103
|
require_relative 'header/eap'
|
101
|
-
require_relative 'header/esp'
|
102
|
-
require_relative 'header/ike'
|
103
104
|
require_relative 'header/dns'
|
104
105
|
require_relative 'header/asn1_base'
|
105
106
|
require_relative 'header/snmp'
|
@@ -114,5 +115,4 @@ require_relative 'header/mld'
|
|
114
115
|
require_relative 'header/mldv2'
|
115
116
|
require_relative 'header/ospfv2'
|
116
117
|
require_relative 'header/ospfv3'
|
117
|
-
require_relative 'header/netbios'
|
118
118
|
require_relative 'header/mdns'
|
@@ -25,7 +25,14 @@ module PacketGen
|
|
25
25
|
# @return [String]
|
26
26
|
# @since 2.0.0
|
27
27
|
def self.protocol_name
|
28
|
-
|
28
|
+
return @protocol_name if defined? @protocol_name
|
29
|
+
|
30
|
+
classname = to_s
|
31
|
+
@protocol_name = if classname.start_with?('PacketGen::Header')
|
32
|
+
classname.sub(/.*Header::/, '')
|
33
|
+
else
|
34
|
+
classname.sub(/.*::/, '')
|
35
|
+
end
|
29
36
|
end
|
30
37
|
|
31
38
|
# Define some methods from given ASN.1 fields to mimic {Base} attributes
|
@@ -42,21 +49,14 @@ module PacketGen
|
|
42
49
|
# Return header protocol name
|
43
50
|
# @return [String]
|
44
51
|
def protocol_name
|
45
|
-
|
46
|
-
|
47
|
-
classname = self.class.to_s
|
48
|
-
@protocol_name = if classname.start_with?('PacketGen::Header')
|
49
|
-
classname.sub(/.*Header::/, '')
|
50
|
-
else
|
51
|
-
classname.sub(/.*::/, '')
|
52
|
-
end
|
52
|
+
self.class.protocol_name
|
53
53
|
end
|
54
54
|
|
55
55
|
# return header method name
|
56
56
|
# @return [String]
|
57
57
|
# @since 2.0.0
|
58
58
|
def method_name
|
59
|
-
return @method_name if @method_name
|
59
|
+
return @method_name if defined? @method_name
|
60
60
|
|
61
61
|
@method_name = protocol_name.downcase.sub(/::/, '_')
|
62
62
|
end
|
@@ -11,7 +11,7 @@ module PacketGen
|
|
11
11
|
# Subclasses may define magic methods:
|
12
12
|
# * +#calc_checksum+, which computes header checksum,
|
13
13
|
# * +#calc_length+, which computes header length,
|
14
|
-
# *
|
14
|
+
# * {#parse?},
|
15
15
|
# * +#reply!+, which inverts needed fields to forge a response.
|
16
16
|
# @author Sylvain Daubert
|
17
17
|
class Base < Types::Fields
|
@@ -78,30 +78,21 @@ module PacketGen
|
|
78
78
|
class Bindings
|
79
79
|
include Enumerable
|
80
80
|
|
81
|
-
# op type
|
82
|
-
# @return [:or,:and]
|
83
|
-
attr_accessor :op
|
84
81
|
# @return [Array<Binding>]
|
85
82
|
attr_accessor :bindings
|
86
83
|
|
87
|
-
|
88
|
-
def initialize(operator)
|
89
|
-
@op = operator
|
84
|
+
def initialize
|
90
85
|
@bindings = []
|
91
86
|
end
|
92
87
|
|
93
88
|
def new_set
|
94
|
-
@bindings << []
|
89
|
+
@bindings << []
|
95
90
|
end
|
96
91
|
|
97
92
|
# @param [Object] arg
|
98
|
-
# @return [
|
93
|
+
# @return [Bindings] self
|
99
94
|
def <<(arg)
|
100
|
-
|
101
|
-
@bindings.last << arg
|
102
|
-
else
|
103
|
-
@bindings << arg
|
104
|
-
end
|
95
|
+
@bindings.last << arg
|
105
96
|
end
|
106
97
|
|
107
98
|
# each iterator
|
@@ -117,15 +108,12 @@ module PacketGen
|
|
117
108
|
@bindings.empty?
|
118
109
|
end
|
119
110
|
|
111
|
+
# Return binding as a hash.
|
120
112
|
# @return [Hash]
|
121
113
|
def to_h
|
122
114
|
hsh = {}
|
123
115
|
each do |b|
|
124
|
-
|
125
|
-
b.each { |sb| hsh[sb.key] = sb.value }
|
126
|
-
else
|
127
|
-
hsh[b.key] = b.value
|
128
|
-
end
|
116
|
+
b.each { |sb| hsh[sb.key] = sb.value }
|
129
117
|
end
|
130
118
|
hsh
|
131
119
|
end
|
@@ -134,26 +122,14 @@ module PacketGen
|
|
134
122
|
# @param [Types::Fields] fields
|
135
123
|
# @return [Boolean]
|
136
124
|
def check?(fields)
|
137
|
-
|
138
|
-
when :or
|
139
|
-
empty? || @bindings.any? { |binding| binding.check?(fields) }
|
140
|
-
when :and
|
141
|
-
@bindings.all? { |binding| binding.check?(fields) }
|
142
|
-
when :newstyle
|
143
|
-
@bindings.any? { |group| group.all? { |binding| binding.check?(fields) } }
|
144
|
-
end
|
125
|
+
@bindings.any? { |group| group.all? { |binding| binding.check?(fields) } }
|
145
126
|
end
|
146
127
|
|
147
128
|
# Set +fields+ to bindings value
|
148
129
|
# @param [Types::Fields] fields
|
149
130
|
# @return [void]
|
150
131
|
def set(fields)
|
151
|
-
|
152
|
-
when Array
|
153
|
-
@bindings.first.each { |b| b.set fields }
|
154
|
-
else
|
155
|
-
@bindings.each { |b| b.set fields }
|
156
|
-
end
|
132
|
+
@bindings.first.each { |b| b.set fields }
|
157
133
|
end
|
158
134
|
end
|
159
135
|
|
@@ -161,6 +137,7 @@ module PacketGen
|
|
161
137
|
# @return [Packet,nil]
|
162
138
|
attr_reader :packet
|
163
139
|
|
140
|
+
# @private
|
164
141
|
# On inheritage, create +@known_header+ class variable
|
165
142
|
# @param [Class] klass
|
166
143
|
# @return [void]
|
@@ -169,79 +146,41 @@ module PacketGen
|
|
169
146
|
klass.class_eval { @known_headers = {} }
|
170
147
|
end
|
171
148
|
|
172
|
-
# Bind a upper header to current
|
173
|
-
# Header1.bind_header Header2, field1: 43
|
174
|
-
# Header1.bind_header Header3, field1: 43, field2: 43
|
175
|
-
# Header1.bind_header Header4, op: :and, field1: 43, field2: 43
|
176
|
-
# Header1.bind_header Header5, field1: ->(v) { v.nil? ? 128 : v > 127 }
|
177
|
-
# Header1.bind_header Header6, procs: [->(hdr) { hdr.field1 = 1 }
|
178
|
-
# ->(hdr) { hdr.field1 == 1 && hdr.body[0..1] == "\x00\x00" }]
|
149
|
+
# Bind a upper header to current one.
|
179
150
|
# @param [Class] header_klass header class to bind to current class
|
180
151
|
# @param [Hash] args current class fields and their value when +header_klass+
|
181
|
-
# is embedded in current class.
|
182
|
-
# is the value extracted from header field (or +nil+ when lambda is used to set
|
183
|
-
# field while adding a header).
|
152
|
+
# is embedded in current class.
|
184
153
|
#
|
185
|
-
#
|
186
|
-
#
|
187
|
-
#
|
188
|
-
# to parse it).
|
154
|
+
# Given value may be a lambda, whose alone argument is the value extracted
|
155
|
+
# from header field (or +nil+ when lambda is used to set field while adding
|
156
|
+
# a header).
|
189
157
|
#
|
190
158
|
# Special key +procs+ may be used to set 2 lambdas, the former to set
|
191
159
|
# fields, the latter to check bindings. This may be used when multiple and
|
192
160
|
# non-trivial checks should be made.
|
193
161
|
# @return [void]
|
194
|
-
# @
|
195
|
-
def self.bind_header(header_klass, args={})
|
196
|
-
Deprecation.deprecated(self, __method__, 'bind', klass_method: true)
|
197
|
-
op = args.delete(:op) || :or
|
198
|
-
if @known_headers[header_klass].nil? || @known_headers[header_klass].op != op
|
199
|
-
bindings = Bindings.new(op)
|
200
|
-
@known_headers[header_klass] = bindings
|
201
|
-
else
|
202
|
-
bindings = @known_headers[header_klass]
|
203
|
-
end
|
204
|
-
args.each do |key, value|
|
205
|
-
bindings << if key == :procs
|
206
|
-
ProcBinding.new(value)
|
207
|
-
else
|
208
|
-
Binding.new(key, value)
|
209
|
-
end
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
|
-
# Bind a upper header to current one.
|
162
|
+
# @example Basic examples
|
214
163
|
# # Bind Header2 to Header1 when field1 from Header1 has a value of 42
|
215
164
|
# Header1.bind Header2, field1: 42
|
216
165
|
# # Bind Header3 to Header1 when field1 from Header1 has a value of 43
|
217
166
|
# # and field2 has value 43 or 44
|
218
167
|
# Header1.bind Header3, field1: 43, field2: 43
|
219
168
|
# Header1.bind Header3, field1: 43, field2: 44
|
169
|
+
# @example Defining a binding on a field using a lambda.
|
220
170
|
# # Bind Header4 to Header1 when field1 from Header1 has a value
|
221
171
|
# # greater or equal to 44. When adding a Header2 to a Header1
|
222
172
|
# # with Packet#add, force value to 44.
|
223
173
|
# Header1.bind Header4, field1: ->(v) { v.nil? ? 44 : v >= 44 }
|
174
|
+
# @example Defining a binding using procs key
|
224
175
|
# # Bind Header5 to Header1 when field1 from Header1 has a value of 41
|
225
176
|
# # and first two bytes of header1's body are null.
|
226
177
|
# # When adding a Header2 to a Header1 with Packet#add, force value to 44.
|
227
178
|
# Header1.bind Header5, procs: [->(hdr) { hdr.field1 = 41 }
|
228
179
|
# ->(hdr) { hdr.field1 == 41 && hdr.body[0..1] == "\x00\x00" }]
|
229
|
-
# @param [Class] header_klass header class to bind to current class
|
230
|
-
# @param [Hash] args current class fields and their value when +header_klass+
|
231
|
-
# is embedded in current class.
|
232
|
-
#
|
233
|
-
# Given value may be a lambda, whose alone argument is the value extracted
|
234
|
-
# from header field (or +nil+ when lambda is used to set field while adding
|
235
|
-
# a header).
|
236
|
-
#
|
237
|
-
# Special key +procs+ may be used to set 2 lambdas, the former to set
|
238
|
-
# fields, the latter to check bindings. This may be used when multiple and
|
239
|
-
# non-trivial checks should be made.
|
240
|
-
# @return [void]
|
241
180
|
# @since 2.7.0
|
242
181
|
def self.bind(header_klass, args={})
|
243
182
|
if @known_headers[header_klass].nil?
|
244
|
-
bindings = Bindings.new
|
183
|
+
bindings = Bindings.new
|
245
184
|
@known_headers[header_klass] = bindings
|
246
185
|
else
|
247
186
|
bindings = @known_headers[header_klass]
|
@@ -260,7 +199,14 @@ module PacketGen
|
|
260
199
|
# @return [String]
|
261
200
|
# @since 2.0.0
|
262
201
|
def self.protocol_name
|
263
|
-
|
202
|
+
return @protocol_name if defined? @protocol_name
|
203
|
+
|
204
|
+
classname = to_s
|
205
|
+
@protocol_name = if classname.start_with?('PacketGen::Header')
|
206
|
+
classname.sub(/.*Header::/, '')
|
207
|
+
else
|
208
|
+
classname.sub(/.*::/, '')
|
209
|
+
end
|
264
210
|
end
|
265
211
|
|
266
212
|
# Helper method to calculate length of +hdr+ and set its +length+ field.
|
@@ -272,7 +218,7 @@ module PacketGen
|
|
272
218
|
length = if header_in_size
|
273
219
|
hdr.sz
|
274
220
|
else
|
275
|
-
hdr
|
221
|
+
hdr[:body].sz
|
276
222
|
end
|
277
223
|
hdr.length = length
|
278
224
|
end
|
@@ -293,14 +239,7 @@ module PacketGen
|
|
293
239
|
# Return header protocol name
|
294
240
|
# @return [String]
|
295
241
|
def protocol_name
|
296
|
-
|
297
|
-
|
298
|
-
classname = self.class.to_s
|
299
|
-
@protocol_name = if classname.start_with?('PacketGen::Header')
|
300
|
-
classname.sub(/.*Header::/, '')
|
301
|
-
else
|
302
|
-
classname.sub(/.*::/, '')
|
303
|
-
end
|
242
|
+
self.class.protocol_name
|
304
243
|
end
|
305
244
|
|
306
245
|
# return header method name
|
@@ -308,7 +247,7 @@ module PacketGen
|
|
308
247
|
# @since 2.0.0
|
309
248
|
# @since 2.8.6 permit multiple nesting levels
|
310
249
|
def method_name
|
311
|
-
return @method_name if @method_name
|
250
|
+
return @method_name if defined? @method_name
|
312
251
|
|
313
252
|
@method_name = protocol_name.downcase.gsub(/::/, '_')
|
314
253
|
end
|
@@ -340,29 +279,30 @@ module PacketGen
|
|
340
279
|
def added_to_packet(packet) end
|
341
280
|
|
342
281
|
# @api private
|
343
|
-
# Get +header+ id in
|
282
|
+
# Get +header+ id in {Packet#headers} array
|
344
283
|
# @param [Header] header
|
345
284
|
# @return [Integer]
|
346
|
-
# @raise FormatError +header+ not in a packet
|
285
|
+
# @raise [FormatError] +header+ not in a packet
|
347
286
|
def header_id(header)
|
348
287
|
raise FormatError, "header of type #{header.class} not in a packet" if packet.nil?
|
288
|
+
|
349
289
|
id = packet.headers.index(header)
|
350
|
-
if id.nil?
|
351
|
-
|
352
|
-
end
|
290
|
+
raise FormatError, "header of type #{header.class} not in packet #{packet}" if id.nil?
|
291
|
+
|
353
292
|
id
|
354
293
|
end
|
355
294
|
|
356
295
|
# @api private
|
357
|
-
# Get IP or IPv6 previous header from +header+
|
296
|
+
# Get {IP} or {IPv6} previous header from +header+
|
358
297
|
# @param [Header] header
|
359
298
|
# @return [Header]
|
360
|
-
# @raise FormatError no IP or IPv6 header previous +header+ in packet
|
361
|
-
# @raise FormatError +header+ not in a packet
|
299
|
+
# @raise [FormatError] no IP or IPv6 header previous +header+ in packet
|
300
|
+
# @raise [FormatError] +header+ not in a packet
|
362
301
|
def ip_header(header)
|
363
302
|
hid = header_id(header)
|
364
303
|
iph = packet.headers[0...hid].reverse.find { |h| h.is_a?(IP) || h.is_a?(IPv6) }
|
365
304
|
raise FormatError, 'no IP or IPv6 header in packet' if iph.nil?
|
305
|
+
|
366
306
|
iph
|
367
307
|
end
|
368
308
|
|
@@ -370,12 +310,13 @@ module PacketGen
|
|
370
310
|
# Get link layer header from given header
|
371
311
|
# @param [Header] header
|
372
312
|
# @return [Header]
|
373
|
-
# @raise FormatError no link layer header in packet
|
374
|
-
# @raise FormatError +header+ not in a packet
|
313
|
+
# @raise [FormatError] no link layer header in packet
|
314
|
+
# @raise [FormatError] +header+ not in a packet
|
375
315
|
def ll_header(header)
|
376
316
|
hid = header_id(header)
|
377
317
|
llh = packet.headers[0...hid].reverse.find { |h| h.is_a?(Eth) || h.is_a?(Dot11) }
|
378
318
|
raise FormatError, 'no link layer header in packet' if llh.nil?
|
319
|
+
|
379
320
|
llh
|
380
321
|
end
|
381
322
|
end
|