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