packetgen 2.6.0 → 2.7.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/.gitignore +1 -0
- data/.rubocop.yml +28 -0
- data/Rakefile +6 -6
- data/bin/pgconsole +6 -6
- data/lib/packetgen.rb +4 -3
- data/lib/packetgen/capture.rb +5 -7
- data/lib/packetgen/config.rb +3 -3
- data/lib/packetgen/deprecation.rb +17 -0
- data/lib/packetgen/header.rb +40 -38
- data/lib/packetgen/header/arp.rb +46 -31
- data/lib/packetgen/header/asn1_base.rb +8 -8
- data/lib/packetgen/header/base.rb +108 -36
- data/lib/packetgen/header/bootp.rb +28 -19
- data/lib/packetgen/header/crypto.rb +6 -8
- data/lib/packetgen/header/dhcp.rb +4 -5
- data/lib/packetgen/header/dhcp/option.rb +46 -34
- data/lib/packetgen/header/dhcp/options.rb +0 -1
- data/lib/packetgen/header/dhcpv6.rb +10 -10
- data/lib/packetgen/header/dhcpv6/duid.rb +2 -3
- data/lib/packetgen/header/dhcpv6/option.rb +16 -21
- data/lib/packetgen/header/dhcpv6/relay.rb +6 -4
- data/lib/packetgen/header/dns.rb +13 -11
- data/lib/packetgen/header/dns/name.rb +4 -6
- data/lib/packetgen/header/dns/opt.rb +31 -31
- data/lib/packetgen/header/dns/option.rb +0 -2
- data/lib/packetgen/header/dns/qdsection.rb +1 -2
- data/lib/packetgen/header/dns/question.rb +19 -13
- data/lib/packetgen/header/dns/rr.rb +11 -14
- data/lib/packetgen/header/dns/rrsection.rb +5 -7
- data/lib/packetgen/header/dot11.rb +45 -29
- data/lib/packetgen/header/dot11/control.rb +3 -5
- data/lib/packetgen/header/dot11/data.rb +34 -6
- data/lib/packetgen/header/dot11/element.rb +0 -1
- data/lib/packetgen/header/dot11/management.rb +9 -5
- data/lib/packetgen/header/dot11/sub_mngt.rb +13 -14
- data/lib/packetgen/header/dot1q.rb +2 -2
- data/lib/packetgen/header/dot1x.rb +3 -4
- data/lib/packetgen/header/eap.rb +62 -53
- data/lib/packetgen/header/eap/fast.rb +0 -1
- data/lib/packetgen/header/eap/md5.rb +1 -2
- data/lib/packetgen/header/eap/tls.rb +9 -10
- data/lib/packetgen/header/eap/ttls.rb +9 -10
- data/lib/packetgen/header/esp.rb +33 -33
- data/lib/packetgen/header/eth.rb +11 -8
- data/lib/packetgen/header/gre.rb +5 -6
- data/lib/packetgen/header/http/headers.rb +11 -14
- data/lib/packetgen/header/http/request.rb +20 -20
- data/lib/packetgen/header/http/response.rb +16 -18
- data/lib/packetgen/header/http/verbs.rb +5 -5
- data/lib/packetgen/header/icmp.rb +1 -3
- data/lib/packetgen/header/icmpv6.rb +1 -3
- data/lib/packetgen/header/igmp.rb +5 -6
- data/lib/packetgen/header/igmpv3.rb +5 -9
- data/lib/packetgen/header/igmpv3/group_record.rb +4 -5
- data/lib/packetgen/header/igmpv3/mq.rb +2 -2
- data/lib/packetgen/header/igmpv3/mr.rb +4 -3
- data/lib/packetgen/header/ike.rb +33 -8
- data/lib/packetgen/header/ike/auth.rb +4 -6
- data/lib/packetgen/header/ike/cert.rb +0 -2
- data/lib/packetgen/header/ike/certreq.rb +1 -3
- data/lib/packetgen/header/ike/id.rb +1 -3
- data/lib/packetgen/header/ike/ke.rb +0 -2
- data/lib/packetgen/header/ike/nonce.rb +0 -2
- data/lib/packetgen/header/ike/notify.rb +22 -24
- data/lib/packetgen/header/ike/payload.rb +198 -199
- data/lib/packetgen/header/ike/sa.rb +21 -30
- data/lib/packetgen/header/ike/sk.rb +16 -17
- data/lib/packetgen/header/ike/ts.rb +22 -24
- data/lib/packetgen/header/ike/vendor_id.rb +0 -2
- data/lib/packetgen/header/ip.rb +30 -23
- data/lib/packetgen/header/ip/addr.rb +5 -6
- data/lib/packetgen/header/ip/option.rb +11 -15
- data/lib/packetgen/header/ip/options.rb +1 -2
- data/lib/packetgen/header/ipv6.rb +27 -12
- data/lib/packetgen/header/ipv6/addr.rb +2 -2
- data/lib/packetgen/header/ipv6/extension.rb +1 -1
- data/lib/packetgen/header/ipv6/hop_by_hop.rb +11 -11
- data/lib/packetgen/header/llc.rb +4 -3
- data/lib/packetgen/header/mdns.rb +11 -5
- data/lib/packetgen/header/mld.rb +4 -4
- data/lib/packetgen/header/mldv2.rb +4 -3
- data/lib/packetgen/header/mldv2/mcast_address_record.rb +3 -4
- data/lib/packetgen/header/mldv2/mlq.rb +3 -4
- data/lib/packetgen/header/mldv2/mlr.rb +4 -3
- data/lib/packetgen/header/netbios.rb +18 -5
- data/lib/packetgen/header/ospfv2.rb +6 -7
- data/lib/packetgen/header/ospfv2/db_description.rb +3 -4
- data/lib/packetgen/header/ospfv2/hello.rb +2 -3
- data/lib/packetgen/header/ospfv2/ls_ack.rb +2 -3
- data/lib/packetgen/header/ospfv2/ls_request.rb +2 -3
- data/lib/packetgen/header/ospfv2/ls_update.rb +5 -6
- data/lib/packetgen/header/ospfv2/lsa.rb +13 -14
- data/lib/packetgen/header/ospfv2/lsa_header.rb +4 -5
- data/lib/packetgen/header/ospfv3.rb +3 -4
- data/lib/packetgen/header/ospfv3/db_description.rb +3 -5
- data/lib/packetgen/header/ospfv3/hello.rb +2 -3
- data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +7 -8
- data/lib/packetgen/header/ospfv3/ls_ack.rb +2 -3
- data/lib/packetgen/header/ospfv3/ls_request.rb +2 -3
- data/lib/packetgen/header/ospfv3/ls_update.rb +5 -6
- data/lib/packetgen/header/ospfv3/lsa.rb +10 -11
- data/lib/packetgen/header/ospfv3/lsa_header.rb +3 -4
- data/lib/packetgen/header/snmp.rb +45 -32
- data/lib/packetgen/header/tcp.rb +13 -9
- data/lib/packetgen/header/tcp/option.rb +16 -11
- data/lib/packetgen/header/tcp/options.rb +3 -4
- data/lib/packetgen/header/tftp.rb +15 -17
- data/lib/packetgen/header/udp.rb +10 -4
- data/lib/packetgen/inspect.rb +7 -9
- data/lib/packetgen/packet.rb +44 -22
- data/lib/packetgen/pcapng.rb +1 -5
- data/lib/packetgen/pcapng/block.rb +17 -11
- data/lib/packetgen/pcapng/epb.rb +6 -11
- data/lib/packetgen/pcapng/file.rb +37 -44
- data/lib/packetgen/pcapng/idb.rb +17 -22
- data/lib/packetgen/pcapng/shb.rb +7 -10
- data/lib/packetgen/pcapng/spb.rb +21 -17
- data/lib/packetgen/pcapng/unknown_block.rb +17 -13
- data/lib/packetgen/proto.rb +1 -2
- data/lib/packetgen/types/array.rb +119 -34
- data/lib/packetgen/types/cstring.rb +1 -5
- data/lib/packetgen/types/enum.rb +8 -10
- data/lib/packetgen/types/fields.rb +34 -28
- data/lib/packetgen/types/int.rb +11 -13
- data/lib/packetgen/types/int_string.rb +6 -8
- data/lib/packetgen/types/oui.rb +3 -6
- data/lib/packetgen/types/string.rb +4 -6
- data/lib/packetgen/types/tlv.rb +11 -14
- data/lib/packetgen/utils.rb +15 -23
- data/lib/packetgen/utils/arp_spoofer.rb +12 -18
- data/lib/packetgen/version.rb +1 -1
- data/packetgen.gemspec +9 -8
- metadata +19 -17
data/lib/packetgen/pcapng/spb.rb
CHANGED
@@ -7,7 +7,6 @@
|
|
7
7
|
|
8
8
|
module PacketGen
|
9
9
|
module PcapNG
|
10
|
-
|
11
10
|
# {SPB} represents a Section Simple Packet Block (SPB) of a pcapng file.
|
12
11
|
#
|
13
12
|
# == Pcapng::SPB Definition
|
@@ -18,9 +17,8 @@ module PacketGen
|
|
18
17
|
# Int32 :block_len2
|
19
18
|
# @author Sylvain Daubert
|
20
19
|
class SPB < Block
|
21
|
-
|
22
20
|
# Minimum SPB size
|
23
|
-
MIN_SIZE
|
21
|
+
MIN_SIZE = 4 * 4
|
24
22
|
|
25
23
|
# @return [:little, :big]
|
26
24
|
attr_accessor :endian
|
@@ -51,21 +49,29 @@ module PacketGen
|
|
51
49
|
self.type = options[:type] || PcapNG::SPB_TYPE.to_i
|
52
50
|
end
|
53
51
|
|
54
|
-
# Has this block
|
52
|
+
# Has this block options?
|
55
53
|
# @return [false]
|
56
|
-
|
54
|
+
# @since 2.7.0
|
55
|
+
def options?
|
57
56
|
false
|
58
57
|
end
|
59
58
|
|
59
|
+
# @deprecated Use {#options?} instead.
|
60
|
+
# @return [false]
|
61
|
+
def has_options?
|
62
|
+
Deprecation.deprecated(self.class, __method__, 'options?')
|
63
|
+
options?
|
64
|
+
end
|
65
|
+
|
60
66
|
# Reads a String or a IO to populate the object
|
61
67
|
# @param [::String,IO] str_or_io
|
62
68
|
# @return [self]
|
63
69
|
def read(str_or_io)
|
64
|
-
if str_or_io.respond_to? :read
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
70
|
+
io = if str_or_io.respond_to? :read
|
71
|
+
str_or_io
|
72
|
+
else
|
73
|
+
StringIO.new(force_binary(str_or_io.to_s))
|
74
|
+
end
|
69
75
|
return self if io.eof?
|
70
76
|
|
71
77
|
self[:type].read io.read(4)
|
@@ -73,11 +79,11 @@ module PacketGen
|
|
73
79
|
self[:orig_len].read io.read(4)
|
74
80
|
# Take care of IDB snaplen
|
75
81
|
# CAUTION: snaplen == 0 -> no capture limit
|
76
|
-
if interface
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
82
|
+
data_len = if interface && (interface.snaplen.to_i > 0)
|
83
|
+
[self[:orig_len].to_i, interface.snaplen.to_i].min
|
84
|
+
else
|
85
|
+
self[:orig_len].to_i
|
86
|
+
end
|
81
87
|
data_pad_len = (4 - (data_len % 4)) % 4
|
82
88
|
self[:data].read io.read(data_len)
|
83
89
|
io.read data_pad_len
|
@@ -95,8 +101,6 @@ module PacketGen
|
|
95
101
|
recalc_block_len
|
96
102
|
super
|
97
103
|
end
|
98
|
-
|
99
104
|
end
|
100
|
-
|
101
105
|
end
|
102
106
|
end
|
@@ -7,13 +7,11 @@
|
|
7
7
|
|
8
8
|
module PacketGen
|
9
9
|
module PcapNG
|
10
|
-
|
11
10
|
# {UnknownBlock} is used to handle unsupported blocks of a pcapng file.
|
12
11
|
# @author Sylvain Daubert
|
13
12
|
class UnknownBlock < Block
|
14
|
-
|
15
13
|
# Minimum Iblock size
|
16
|
-
MIN_SIZE
|
14
|
+
MIN_SIZE = 12
|
17
15
|
|
18
16
|
# @return [:little, :big]
|
19
17
|
attr_accessor :endian
|
@@ -35,21 +33,29 @@ module PacketGen
|
|
35
33
|
recalc_block_len
|
36
34
|
end
|
37
35
|
|
38
|
-
# Has this block
|
36
|
+
# Has this block options?
|
39
37
|
# @return [false]
|
40
|
-
|
38
|
+
# @since 2.7.0
|
39
|
+
def options?
|
41
40
|
false
|
42
41
|
end
|
43
42
|
|
44
|
-
|
43
|
+
# @deprecated Use {#options?} instead.
|
44
|
+
# @return [false]
|
45
|
+
def has_options?
|
46
|
+
Deprecation.deprecated(self.class, __method__, 'options?')
|
47
|
+
options?
|
48
|
+
end
|
49
|
+
|
50
|
+
# Reads a String or a IO to populate the object
|
45
51
|
# @param [::String,IO] str_or_io
|
46
52
|
# @return [self]
|
47
53
|
def read(str_or_io)
|
48
|
-
if str_or_io.respond_to? :read
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
54
|
+
io = if str_or_io.respond_to? :read
|
55
|
+
str_or_io
|
56
|
+
else
|
57
|
+
StringIO.new(force_binary(str_or_io.to_s))
|
58
|
+
end
|
53
59
|
return self if io.eof?
|
54
60
|
|
55
61
|
self[:type].read io.read(4)
|
@@ -71,8 +77,6 @@ module PacketGen
|
|
71
77
|
recalc_block_len
|
72
78
|
super
|
73
79
|
end
|
74
|
-
|
75
80
|
end
|
76
|
-
|
77
81
|
end
|
78
82
|
end
|
data/lib/packetgen/proto.rb
CHANGED
@@ -5,15 +5,14 @@
|
|
5
5
|
# This program is published under MIT license.
|
6
6
|
|
7
7
|
# frozen_string_literal: true
|
8
|
+
|
8
9
|
require 'socket'
|
9
10
|
|
10
11
|
module PacketGen
|
11
|
-
|
12
12
|
# Module handling some helper methods for protocols
|
13
13
|
# @author Sylvain Daubert
|
14
14
|
# @since 2.1.2
|
15
15
|
module Proto
|
16
|
-
|
17
16
|
# @private cache information used by {.getprotobyname} and
|
18
17
|
# {.getprotobynumber}
|
19
18
|
def self.prepare_cache
|
@@ -7,7 +7,6 @@
|
|
7
7
|
|
8
8
|
module PacketGen
|
9
9
|
module Types
|
10
|
-
|
11
10
|
# @abstract Base class to define set of {Fields} subclasses.
|
12
11
|
# == #record_from_hash
|
13
12
|
# Subclasses should define private method +#record_from_hash+. This method
|
@@ -16,7 +15,8 @@ module PacketGen
|
|
16
15
|
# A default method is defined by {Array}: it calls constructor of class defined
|
17
16
|
# by {.set_of}.
|
18
17
|
# @author Sylvain Daubert
|
19
|
-
class Array
|
18
|
+
class Array
|
19
|
+
include Enumerable
|
20
20
|
|
21
21
|
# Separator used in {#to_human}.
|
22
22
|
# May be ovverriden by subclasses
|
@@ -25,33 +25,95 @@ module PacketGen
|
|
25
25
|
# Define type of objects in set. Used by {#read} and {#push}.
|
26
26
|
# @param [Class] klass
|
27
27
|
# @return [void]
|
28
|
+
# rubocop:disable Naming/AccessorMethodName
|
28
29
|
def self.set_of(klass)
|
29
30
|
@klass = klass
|
30
31
|
end
|
32
|
+
# rubocop:enable Naming/AccessorMethodName
|
31
33
|
|
32
34
|
# @param [Hash] options
|
33
35
|
# @option options [Int] counter Int object used as a counter for this set
|
34
36
|
def initialize(options={})
|
35
|
-
super()
|
36
37
|
@counter = options[:counter]
|
38
|
+
@array = []
|
37
39
|
end
|
38
40
|
|
39
|
-
#
|
40
|
-
#
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
41
|
+
# Initialize array for copy:
|
42
|
+
# * duplicate internal array.
|
43
|
+
def initialize_copy(_other)
|
44
|
+
@array = @array.dup
|
45
|
+
end
|
46
|
+
|
47
|
+
# Return the element at +index+.
|
48
|
+
# @param [integer] index
|
49
|
+
# @return [Object]
|
50
|
+
def [](index)
|
51
|
+
@array[index]
|
52
|
+
end
|
53
|
+
|
54
|
+
def ==(other)
|
55
|
+
case other
|
56
|
+
when Array
|
57
|
+
@array == other.to_a
|
58
|
+
else
|
59
|
+
@array == other
|
53
60
|
end
|
54
|
-
|
61
|
+
end
|
62
|
+
|
63
|
+
# Clear array.
|
64
|
+
# @return [void]
|
65
|
+
def clear
|
66
|
+
@array.clear
|
67
|
+
end
|
68
|
+
|
69
|
+
# Clear array. Reset associated counter, if any.
|
70
|
+
# @return [void]
|
71
|
+
def clear!
|
72
|
+
@array.clear
|
73
|
+
@counter.read(0) if @counter
|
74
|
+
end
|
75
|
+
|
76
|
+
# Delete an object from this array. Update associated counter if any
|
77
|
+
# @param [Object] obj
|
78
|
+
# @return [Object] deleted object
|
79
|
+
def delete(obj)
|
80
|
+
deleted = @array.delete(obj)
|
81
|
+
@counter.read(@counter.to_i - 1) if @counter && deleted
|
82
|
+
deleted
|
83
|
+
end
|
84
|
+
|
85
|
+
# Delete element at +index+.
|
86
|
+
# @param [Integer] index
|
87
|
+
# @return [Object,nil] deleted object
|
88
|
+
def delete_at(index)
|
89
|
+
deleted = @array.delete_at(index)
|
90
|
+
@counter.read(@counter.to_i - 1) if @counter && deleted
|
91
|
+
deleted
|
92
|
+
end
|
93
|
+
|
94
|
+
# Calls the given block once for each element in self, passing that
|
95
|
+
# element as a parameter. Returns the array itself.
|
96
|
+
# @return [Array]
|
97
|
+
def each
|
98
|
+
@array.each { |el| yield el }
|
99
|
+
end
|
100
|
+
|
101
|
+
# Return +true+ if contains no element.
|
102
|
+
# @return [Booelan]
|
103
|
+
def empty?
|
104
|
+
@array.empty?
|
105
|
+
end
|
106
|
+
|
107
|
+
# Return first element
|
108
|
+
# @return [Object]
|
109
|
+
def first
|
110
|
+
@array.first
|
111
|
+
end
|
112
|
+
|
113
|
+
# Return last element.
|
114
|
+
# @return [Object]
|
115
|
+
def last
|
116
|
+
@array.last
|
55
117
|
end
|
56
118
|
|
57
119
|
# @abstract depend on private method +#record_from_hash+ which should be
|
@@ -66,7 +128,8 @@ module PacketGen
|
|
66
128
|
else
|
67
129
|
obj
|
68
130
|
end
|
69
|
-
|
131
|
+
@array << obj
|
132
|
+
self
|
70
133
|
end
|
71
134
|
|
72
135
|
# @abstract depend on private method +#record_from_hash+ which should be
|
@@ -80,31 +143,53 @@ module PacketGen
|
|
80
143
|
self
|
81
144
|
end
|
82
145
|
|
83
|
-
#
|
84
|
-
# @param [
|
85
|
-
# @return [
|
86
|
-
def
|
87
|
-
|
88
|
-
|
89
|
-
|
146
|
+
# Populate object from a string
|
147
|
+
# @param [String] str
|
148
|
+
# @return [self]
|
149
|
+
def read(str)
|
150
|
+
clear
|
151
|
+
return self if str.nil?
|
152
|
+
return self if @counter && @counter.to_i.zero?
|
153
|
+
force_binary str
|
154
|
+
klass = self.class.class_eval { @klass }
|
155
|
+
until str.empty?
|
156
|
+
obj = klass.new.read(str)
|
157
|
+
@array << obj
|
158
|
+
str.slice!(0, obj.sz)
|
159
|
+
break if @counter && self.size == @counter.to_i
|
160
|
+
end
|
161
|
+
self
|
162
|
+
end
|
163
|
+
|
164
|
+
# Get number of element in array
|
165
|
+
# @return [Integer]
|
166
|
+
def size
|
167
|
+
@array.size
|
168
|
+
end
|
169
|
+
alias length size
|
170
|
+
|
171
|
+
# Get size in bytes
|
172
|
+
# @return [Integer]
|
173
|
+
def sz
|
174
|
+
to_s.size
|
175
|
+
end
|
176
|
+
|
177
|
+
# Return an Array
|
178
|
+
# @return [::Array]
|
179
|
+
def to_a
|
180
|
+
@array
|
90
181
|
end
|
91
182
|
|
92
183
|
# Get binary string
|
93
184
|
# @return [String]
|
94
185
|
def to_s
|
95
|
-
map(&:to_s).join
|
186
|
+
@array.map(&:to_s).join
|
96
187
|
end
|
97
188
|
|
98
189
|
# Get a human readable string
|
99
190
|
# @return [String]
|
100
191
|
def to_human
|
101
|
-
map(&:to_human).join(self.class::HUMAN_SEPARATOR)
|
102
|
-
end
|
103
|
-
|
104
|
-
# Get size in bytes
|
105
|
-
# @return [Integer]
|
106
|
-
def sz
|
107
|
-
to_s.size
|
192
|
+
@array.map(&:to_human).join(self.class::HUMAN_SEPARATOR)
|
108
193
|
end
|
109
194
|
|
110
195
|
# Force binary encoding for +str+
|
@@ -8,11 +8,9 @@
|
|
8
8
|
|
9
9
|
module PacketGen
|
10
10
|
module Types
|
11
|
-
|
12
11
|
# This class handles null-terminated strings (aka C strings).
|
13
12
|
# @author Sylvain Daubert
|
14
13
|
class CString < ::String
|
15
|
-
|
16
14
|
# @param [Hash] options
|
17
15
|
# @option options [Integer] :static_length set a static length for this string
|
18
16
|
def initialize(options={})
|
@@ -24,9 +22,7 @@ module PacketGen
|
|
24
22
|
# @return [String] self
|
25
23
|
def read(str)
|
26
24
|
s = str.to_s
|
27
|
-
if @static_length.is_a? Integer
|
28
|
-
s = s[0, @static_length]
|
29
|
-
end
|
25
|
+
s = s[0, @static_length] if @static_length.is_a? Integer
|
30
26
|
idx = s.index(0.chr)
|
31
27
|
s = s[0, idx] unless idx.nil?
|
32
28
|
self.replace s
|
data/lib/packetgen/types/enum.rb
CHANGED
@@ -8,7 +8,6 @@
|
|
8
8
|
|
9
9
|
module PacketGen
|
10
10
|
module Types
|
11
|
-
|
12
11
|
# @abstract Base enum class to handle binary integers with limited
|
13
12
|
# authorized values
|
14
13
|
# An {Enum} type is used to handle an {Int} field with limited
|
@@ -31,7 +30,6 @@ module PacketGen
|
|
31
30
|
# @since 2.1.3
|
32
31
|
# @author Sylvain Daubert
|
33
32
|
class Enum < Int
|
34
|
-
|
35
33
|
# @return [Hash]
|
36
34
|
attr_reader :enum
|
37
35
|
|
@@ -47,25 +45,25 @@ module PacketGen
|
|
47
45
|
end
|
48
46
|
|
49
47
|
# Setter for value attribute
|
50
|
-
# @param [Integer, String,nil]
|
48
|
+
# @param [Integer, String,nil] value value as an Integer or as a String
|
51
49
|
# from enumration
|
52
50
|
# @return [Integer]
|
53
|
-
def value=(
|
54
|
-
ival = case
|
51
|
+
def value=(value)
|
52
|
+
ival = case value
|
55
53
|
when NilClass
|
56
54
|
nil
|
57
55
|
when ::String
|
58
|
-
raise ArgumentError, "#{
|
59
|
-
@enum[
|
56
|
+
raise ArgumentError, "#{value.inspect} not in enumeration" unless @enum.key? value
|
57
|
+
@enum[value]
|
60
58
|
else
|
61
|
-
raise ArgumentError, "#{
|
62
|
-
|
59
|
+
raise ArgumentError, "#{value.inspect} not in enumeration" unless @enum.value? value
|
60
|
+
value
|
63
61
|
end
|
64
62
|
@value = ival
|
65
63
|
end
|
66
64
|
|
67
65
|
# To handle human API: set value from a String
|
68
|
-
alias
|
66
|
+
alias from_human value=
|
69
67
|
|
70
68
|
# Get human readable value (enum name)
|
71
69
|
# @return [String]
|
@@ -7,7 +7,6 @@
|
|
7
7
|
|
8
8
|
module PacketGen
|
9
9
|
module Types
|
10
|
-
|
11
10
|
# @abstract Set of fields
|
12
11
|
# This class is a base class to define headers or anything else with a binary
|
13
12
|
# format containing multiple fields.
|
@@ -93,7 +92,6 @@ module PacketGen
|
|
93
92
|
# offset subfield from +frag+ field.
|
94
93
|
# @author Sylvain Daubert
|
95
94
|
class Fields
|
96
|
-
|
97
95
|
# @private
|
98
96
|
@ordered_fields = []
|
99
97
|
# @private
|
@@ -149,10 +147,10 @@ module PacketGen
|
|
149
147
|
elsif type < Types::Int
|
150
148
|
define << "def #{name}; self[:#{name}].to_i; end"
|
151
149
|
define << "def #{name}=(val) self[:#{name}].read val; end"
|
152
|
-
elsif type.instance_methods.include?
|
153
|
-
|
154
|
-
|
155
|
-
|
150
|
+
elsif type.instance_methods.include?(:to_human) &&
|
151
|
+
type.instance_methods.include?(:from_human)
|
152
|
+
define << "def #{name}; self[:#{name}].to_human; end"
|
153
|
+
define << "def #{name}=(val) self[:#{name}].from_human val; end"
|
156
154
|
else
|
157
155
|
define << "def #{name}; self[:#{name}]; end\n"
|
158
156
|
define << "def #{name}=(val) self[:#{name}].read val; end"
|
@@ -179,12 +177,11 @@ module PacketGen
|
|
179
177
|
# @see .define_field
|
180
178
|
def self.define_field_before(other, name, type, options={})
|
181
179
|
define_field name, type, options
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
end
|
180
|
+
return if other.nil?
|
181
|
+
@ordered_fields.delete name
|
182
|
+
idx = @ordered_fields.index(other)
|
183
|
+
raise ArgumentError, "unknown #{other} field" if idx.nil?
|
184
|
+
@ordered_fields[idx, 0] = name
|
188
185
|
end
|
189
186
|
|
190
187
|
# Define a field, after another one
|
@@ -197,12 +194,11 @@ module PacketGen
|
|
197
194
|
# @see .define_field
|
198
195
|
def self.define_field_after(other, name, type, options={})
|
199
196
|
define_field name, type, options
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
end
|
197
|
+
return if other.nil?
|
198
|
+
@ordered_fields.delete name
|
199
|
+
idx = @ordered_fields.index(other)
|
200
|
+
raise ArgumentError, "unknown #{other} field" if idx.nil?
|
201
|
+
@ordered_fields[idx + 1, 0] = name
|
206
202
|
end
|
207
203
|
|
208
204
|
# Delete a previously defined field
|
@@ -256,7 +252,7 @@ module PacketGen
|
|
256
252
|
clear_mask = (2**total_size - 1) & (~field_mask & (2**total_size - 1))
|
257
253
|
|
258
254
|
if size == 1
|
259
|
-
class_eval <<-
|
255
|
+
class_eval <<-METHODS
|
260
256
|
def #{field}?
|
261
257
|
val = (self[:#{attr}].to_i & #{field_mask}) >> #{shift}
|
262
258
|
val != 0
|
@@ -266,9 +262,9 @@ module PacketGen
|
|
266
262
|
self[:#{attr}].value = self[:#{attr}].to_i & #{clear_mask}
|
267
263
|
self[:#{attr}].value |= val << #{shift}
|
268
264
|
end
|
269
|
-
|
265
|
+
METHODS
|
270
266
|
else
|
271
|
-
|
267
|
+
class_eval <<-METHODS
|
272
268
|
def #{field}
|
273
269
|
(self[:#{attr}].to_i & #{field_mask}) >> #{shift}
|
274
270
|
end
|
@@ -276,7 +272,7 @@ module PacketGen
|
|
276
272
|
self[:#{attr}].value = self[:#{attr}].to_i & #{clear_mask}
|
277
273
|
self[:#{attr}].value |= (v & #{2**size - 1}) << #{shift}
|
278
274
|
end
|
279
|
-
|
275
|
+
METHODS
|
280
276
|
end
|
281
277
|
|
282
278
|
@bit_fields << field
|
@@ -321,8 +317,8 @@ module PacketGen
|
|
321
317
|
@fields[field].read(value)
|
322
318
|
elsif type <= Types::String
|
323
319
|
@fields[field].read(value)
|
324
|
-
|
325
|
-
@fields[field].from_human(value)
|
320
|
+
elsif @fields[field].respond_to? :from_human
|
321
|
+
@fields[field].from_human(value)
|
326
322
|
end
|
327
323
|
|
328
324
|
@optional_fields[field] = optional if optional
|
@@ -361,7 +357,7 @@ module PacketGen
|
|
361
357
|
# Say if this field is optional
|
362
358
|
# @return [Boolean]
|
363
359
|
def is_optional?(field)
|
364
|
-
@optional_fields.
|
360
|
+
@optional_fields.key? field
|
365
361
|
end
|
366
362
|
|
367
363
|
# Say if an optional field is present
|
@@ -414,8 +410,8 @@ module PacketGen
|
|
414
410
|
# Return object as a binary string
|
415
411
|
# @return [String]
|
416
412
|
def to_s
|
417
|
-
fields.select { |f| is_present?(f) }
|
418
|
-
|
413
|
+
fields.select { |f| is_present?(f) }
|
414
|
+
.map! { |f| force_binary @fields[f].to_s }.join
|
419
415
|
end
|
420
416
|
|
421
417
|
# Size of object as binary string
|
@@ -436,7 +432,7 @@ module PacketGen
|
|
436
432
|
# @raise [BodyError] no body on given object
|
437
433
|
# @raise [ArgumentError] cannot cram +body+ in +:body+ field
|
438
434
|
def body=(value)
|
439
|
-
raise BodyError, 'no body field'
|
435
|
+
raise BodyError, 'no body field' unless @fields.key? :body
|
440
436
|
case body
|
441
437
|
when ::String
|
442
438
|
self[:body].read value
|
@@ -455,6 +451,16 @@ module PacketGen
|
|
455
451
|
def force_binary(str)
|
456
452
|
PacketGen.force_binary(str)
|
457
453
|
end
|
454
|
+
|
455
|
+
private
|
456
|
+
|
457
|
+
# Deeply duplicate +@fields+
|
458
|
+
# @return [void]
|
459
|
+
def initialize_copy(_other)
|
460
|
+
fields = {}
|
461
|
+
@fields.each { |k,v| fields[k] = v.dup }
|
462
|
+
@fields = fields
|
463
|
+
end
|
458
464
|
end
|
459
465
|
end
|
460
466
|
end
|