packetgen 3.1.3 → 3.1.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +0 -1
- data/bin/pgconsole +1 -0
- data/lib/packetgen.rb +33 -4
- data/lib/packetgen/capture.rb +51 -28
- data/lib/packetgen/config.rb +17 -11
- data/lib/packetgen/deprecation.rb +33 -7
- data/lib/packetgen/header.rb +2 -9
- data/lib/packetgen/header/arp.rb +2 -2
- data/lib/packetgen/header/asn1_base.rb +2 -2
- data/lib/packetgen/header/base.rb +70 -74
- data/lib/packetgen/header/bootp.rb +3 -3
- data/lib/packetgen/header/dhcp.rb +2 -2
- data/lib/packetgen/header/dhcp/option.rb +2 -2
- data/lib/packetgen/header/dhcp/options.rb +2 -2
- data/lib/packetgen/header/dhcpv6.rb +12 -12
- data/lib/packetgen/header/dhcpv6/duid.rb +11 -5
- data/lib/packetgen/header/dhcpv6/option.rb +8 -16
- data/lib/packetgen/header/dhcpv6/options.rb +2 -2
- data/lib/packetgen/header/dhcpv6/relay.rb +2 -2
- data/lib/packetgen/header/dns.rb +9 -9
- data/lib/packetgen/header/dns/name.rb +20 -9
- data/lib/packetgen/header/dns/opt.rb +2 -2
- data/lib/packetgen/header/dns/option.rb +2 -2
- data/lib/packetgen/header/dns/qdsection.rb +3 -3
- data/lib/packetgen/header/dns/question.rb +37 -35
- data/lib/packetgen/header/dns/rr.rb +3 -3
- data/lib/packetgen/header/dns/rrsection.rb +2 -2
- data/lib/packetgen/header/dot11.rb +30 -51
- data/lib/packetgen/header/dot11/control.rb +5 -5
- data/lib/packetgen/header/dot11/data.rb +11 -7
- data/lib/packetgen/header/dot11/element.rb +16 -16
- data/lib/packetgen/header/dot11/management.rb +2 -2
- data/lib/packetgen/header/dot11/sub_mngt.rb +2 -12
- data/lib/packetgen/header/dot1q.rb +2 -2
- data/lib/packetgen/header/dot1x.rb +7 -20
- data/lib/packetgen/header/eap.rb +30 -33
- data/lib/packetgen/header/eap/fast.rb +2 -2
- data/lib/packetgen/header/eap/md5.rb +2 -2
- data/lib/packetgen/header/eap/tls.rb +2 -2
- data/lib/packetgen/header/eap/ttls.rb +2 -2
- data/lib/packetgen/header/eth.rb +13 -11
- data/lib/packetgen/header/gre.rb +2 -2
- data/lib/packetgen/header/http.rb +2 -0
- data/lib/packetgen/header/http/headers.rb +6 -4
- data/lib/packetgen/header/http/request.rb +36 -21
- data/lib/packetgen/header/http/response.rb +7 -7
- data/lib/packetgen/header/http/verbs.rb +3 -3
- data/lib/packetgen/header/icmp.rb +2 -2
- data/lib/packetgen/header/icmpv6.rb +2 -2
- data/lib/packetgen/header/igmp.rb +4 -4
- data/lib/packetgen/header/igmpv3.rb +3 -3
- data/lib/packetgen/header/igmpv3/group_record.rb +8 -6
- data/lib/packetgen/header/igmpv3/mq.rb +2 -2
- data/lib/packetgen/header/igmpv3/mr.rb +2 -2
- data/lib/packetgen/header/ip.rb +30 -31
- data/lib/packetgen/header/ip/addr.rb +10 -3
- data/lib/packetgen/header/ip/option.rb +8 -10
- data/lib/packetgen/header/ip/options.rb +3 -5
- data/lib/packetgen/header/ipv6.rb +2 -2
- data/lib/packetgen/header/ipv6/addr.rb +9 -2
- data/lib/packetgen/header/ipv6/extension.rb +2 -2
- data/lib/packetgen/header/ipv6/hop_by_hop.rb +3 -3
- data/lib/packetgen/header/llc.rb +2 -2
- data/lib/packetgen/header/mdns.rb +2 -2
- data/lib/packetgen/header/mld.rb +2 -2
- data/lib/packetgen/header/mldv2.rb +2 -2
- data/lib/packetgen/header/mldv2/mcast_address_record.rb +4 -2
- data/lib/packetgen/header/mldv2/mlq.rb +2 -2
- data/lib/packetgen/header/mldv2/mlr.rb +2 -2
- data/lib/packetgen/header/ospfv2.rb +9 -9
- data/lib/packetgen/header/ospfv2/db_description.rb +2 -2
- data/lib/packetgen/header/ospfv2/hello.rb +2 -2
- data/lib/packetgen/header/ospfv2/ls_ack.rb +2 -2
- data/lib/packetgen/header/ospfv2/ls_request.rb +4 -2
- data/lib/packetgen/header/ospfv2/ls_update.rb +2 -2
- data/lib/packetgen/header/ospfv2/lsa.rb +9 -5
- data/lib/packetgen/header/ospfv2/lsa_header.rb +8 -7
- data/lib/packetgen/header/ospfv3.rb +2 -2
- data/lib/packetgen/header/ospfv3/db_description.rb +2 -2
- data/lib/packetgen/header/ospfv3/hello.rb +2 -2
- data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +4 -2
- data/lib/packetgen/header/ospfv3/ls_ack.rb +2 -2
- data/lib/packetgen/header/ospfv3/ls_request.rb +4 -2
- data/lib/packetgen/header/ospfv3/ls_update.rb +2 -2
- data/lib/packetgen/header/ospfv3/lsa.rb +5 -5
- data/lib/packetgen/header/ospfv3/lsa_header.rb +9 -8
- data/lib/packetgen/header/snmp.rb +33 -29
- data/lib/packetgen/header/tcp.rb +4 -23
- data/lib/packetgen/header/tcp/option.rb +11 -11
- data/lib/packetgen/header/tcp/options.rb +2 -2
- data/lib/packetgen/header/tftp.rb +6 -6
- data/lib/packetgen/header/udp.rb +3 -3
- data/lib/packetgen/headerable.rb +5 -4
- data/lib/packetgen/inject.rb +23 -0
- data/lib/packetgen/inspect.rb +23 -20
- data/lib/packetgen/packet.rb +82 -53
- data/lib/packetgen/pcap.rb +29 -0
- data/lib/packetgen/pcapng.rb +13 -13
- data/lib/packetgen/pcapng/block.rb +26 -13
- data/lib/packetgen/pcapng/epb.rb +25 -22
- data/lib/packetgen/pcapng/file.rb +260 -138
- data/lib/packetgen/pcapng/idb.rb +36 -38
- data/lib/packetgen/pcapng/shb.rb +51 -53
- data/lib/packetgen/pcapng/spb.rb +19 -19
- data/lib/packetgen/pcapng/unknown_block.rb +5 -13
- data/lib/packetgen/pcaprub_wrapper.rb +81 -0
- data/lib/packetgen/proto.rb +2 -2
- data/lib/packetgen/types.rb +3 -0
- data/lib/packetgen/types/abstract_tlv.rb +27 -7
- data/lib/packetgen/types/array.rb +22 -15
- data/lib/packetgen/types/cstring.rb +57 -20
- data/lib/packetgen/types/enum.rb +7 -2
- data/lib/packetgen/types/fieldable.rb +65 -0
- data/lib/packetgen/types/fields.rb +182 -117
- data/lib/packetgen/types/int.rb +18 -6
- data/lib/packetgen/types/int_string.rb +10 -2
- data/lib/packetgen/types/length_from.rb +20 -12
- data/lib/packetgen/types/oui.rb +4 -2
- data/lib/packetgen/types/string.rb +59 -8
- data/lib/packetgen/types/tlv.rb +4 -2
- data/lib/packetgen/utils.rb +4 -4
- data/lib/packetgen/utils/arp_spoofer.rb +2 -2
- data/lib/packetgen/version.rb +3 -3
- metadata +39 -61
- data/.gitignore +0 -13
- data/.rubocop.yml +0 -30
- data/.travis.yml +0 -19
- data/Gemfile +0 -4
- data/Rakefile +0 -21
- data/packetgen.gemspec +0 -36
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# This file is part of PacketGen
|
2
4
|
# See https://github.com/sdaubert/packetgen for more informations
|
3
5
|
# Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
|
4
6
|
# This program is published under MIT license.
|
5
7
|
|
6
|
-
#
|
8
|
+
# rubocop:disable Metrics/ClassLength
|
7
9
|
|
8
10
|
module PacketGen
|
9
11
|
module Types
|
@@ -13,8 +15,7 @@ module PacketGen
|
|
13
15
|
#
|
14
16
|
# == Basics
|
15
17
|
# A {Fields} subclass is generaly composed of multiple binary fields. These fields
|
16
|
-
# have each a given type. All
|
17
|
-
# {Fields} subclasses may also be used as field type.
|
18
|
+
# have each a given type. All {Fieldable} types are supported.
|
18
19
|
#
|
19
20
|
# To define a new subclass, it has to inherit from {Fields}. And some class
|
20
21
|
# methods have to be used to declare attributes/fields:
|
@@ -119,17 +120,23 @@ module PacketGen
|
|
119
120
|
# @return [Hash]
|
120
121
|
# @since 3.1.0
|
121
122
|
attr_reader :field_defs
|
123
|
+
# Get bit fields defintions for this class
|
124
|
+
# @return [Hash]
|
125
|
+
# @since 3.1.5
|
126
|
+
attr_reader :bit_fields
|
122
127
|
|
123
128
|
# On inheritage, create +@field_defs+ class variable
|
124
129
|
# @param [Class] klass
|
125
130
|
# @return [void]
|
126
131
|
def inherited(klass)
|
132
|
+
super
|
133
|
+
|
127
134
|
field_defs = {}
|
128
135
|
@field_defs.each do |k, v|
|
129
136
|
field_defs[k] = v.clone
|
130
137
|
end
|
131
138
|
ordered = @ordered_fields.clone
|
132
|
-
bf =
|
139
|
+
bf = bit_fields.clone
|
133
140
|
|
134
141
|
klass.class_eval do
|
135
142
|
@ordered_fields = ordered
|
@@ -158,7 +165,7 @@ module PacketGen
|
|
158
165
|
# bs[value1] # => Types::Int8
|
159
166
|
# bs.value1 # => Integer
|
160
167
|
# @param [Symbol] name field name
|
161
|
-
# @param [
|
168
|
+
# @param [Fieldable] type class or instance
|
162
169
|
# @param [Hash] options Unrecognized options are passed to object builder if
|
163
170
|
# +:builder+ option is not set.
|
164
171
|
# @option options [Object] :default default value. May be a proc. This lambda
|
@@ -172,44 +179,22 @@ module PacketGen
|
|
172
179
|
# Define enumeration: hash's keys are +String+, and values are +Integer+.
|
173
180
|
# @return [void]
|
174
181
|
def define_field(name, type, options={})
|
175
|
-
|
176
|
-
if type < Types::Enum
|
177
|
-
define << "def #{name}; self[:#{name}].to_i; end"
|
178
|
-
define << "def #{name}=(val) self[:#{name}].value = val; end"
|
179
|
-
else
|
180
|
-
define << "def #{name}\n" \
|
181
|
-
" if self[:#{name}].respond_to?(:to_human) && self[:#{name}].respond_to?(:from_human)\n" \
|
182
|
-
" self[:#{name}].to_human\n" \
|
183
|
-
" else\n" \
|
184
|
-
" self[:#{name}]\n" \
|
185
|
-
" end\n" \
|
186
|
-
"end"
|
187
|
-
define << "def #{name}=(val)\n" \
|
188
|
-
" if self[:#{name}].respond_to?(:to_human) && self[:#{name}].respond_to?(:from_human)\n" \
|
189
|
-
" self[:#{name}].from_human val\n" \
|
190
|
-
" else\n" \
|
191
|
-
" self[:#{name}].read val\n" \
|
192
|
-
" end\n" \
|
193
|
-
"end"
|
194
|
-
end
|
195
|
-
|
196
|
-
define.delete_at(1) if instance_methods.include? "#{name}=".to_sym
|
197
|
-
define.delete_at(0) if instance_methods.include? name
|
198
|
-
class_eval define.join("\n")
|
182
|
+
fields << name
|
199
183
|
field_defs[name] = FieldDef.new(type,
|
200
184
|
options.delete(:default),
|
201
185
|
options.delete(:builder),
|
202
186
|
options.delete(:optional),
|
203
187
|
options.delete(:enum),
|
204
188
|
options)
|
205
|
-
|
189
|
+
|
190
|
+
add_methods(name, type)
|
206
191
|
end
|
207
192
|
|
208
193
|
# Define a field, before another one
|
209
194
|
# @param [Symbol,nil] other field name to create a new one before. If +nil+,
|
210
195
|
# new field is appended.
|
211
196
|
# @param [Symbol] name field name to create
|
212
|
-
# @param [
|
197
|
+
# @param [Fieldable] type class or instance
|
213
198
|
# @param [Hash] options See {.define_field}.
|
214
199
|
# @return [void]
|
215
200
|
# @see .define_field
|
@@ -228,7 +213,7 @@ module PacketGen
|
|
228
213
|
# @param [Symbol,nil] other field name to create a new one after. If +nil+,
|
229
214
|
# new field is appended.
|
230
215
|
# @param [Symbol] name field name to create
|
231
|
-
# @param [
|
216
|
+
# @param [Fieldable] type class or instance
|
232
217
|
# @param [Hash] options See {.define_field}.
|
233
218
|
# @return [void]
|
234
219
|
# @see .define_field
|
@@ -262,12 +247,12 @@ module PacketGen
|
|
262
247
|
# @raise [ArgumentError] unknown +field+
|
263
248
|
# @since 2.8.4
|
264
249
|
def update_field(field, options)
|
265
|
-
|
250
|
+
check_existence_of field
|
251
|
+
|
252
|
+
%i[default builder optional enum].each do |property|
|
253
|
+
field_defs_property_from(field, property, options)
|
254
|
+
end
|
266
255
|
|
267
|
-
field_defs[field].default = options.delete(:default) if options.key?(:default)
|
268
|
-
field_defs[field].builder = options.delete(:builder) if options.key?(:builder)
|
269
|
-
field_defs[field].optional = options.delete(:optional) if options.key?(:optional)
|
270
|
-
field_defs[field].enum = options.delete(:enum) if options.key?(:enum)
|
271
256
|
field_defs[field].options.merge!(options)
|
272
257
|
end
|
273
258
|
|
@@ -289,63 +274,29 @@ module PacketGen
|
|
289
274
|
# subclass)
|
290
275
|
# @param [Array] args list of bitfield names. Name may be followed
|
291
276
|
# by bitfield size. If no size is given, 1 bit is assumed.
|
277
|
+
# @raise [ArgumentError] unknown +attr+
|
292
278
|
# @return [void]
|
293
279
|
def define_bit_fields_on(attr, *args)
|
294
|
-
|
295
|
-
raise ArgumentError, "unknown #{attr} field" if attr_def.nil?
|
280
|
+
check_existence_of attr
|
296
281
|
|
297
|
-
type =
|
298
|
-
unless type < Types::Int
|
299
|
-
raise TypeError, "#{attr} is not a PacketGen::Types::Int"
|
300
|
-
end
|
282
|
+
type = field_defs[attr].type
|
283
|
+
raise TypeError, "#{attr} is not a PacketGen::Types::Int" unless type < Types::Int
|
301
284
|
|
302
285
|
total_size = type.new.width * 8
|
303
286
|
idx = total_size - 1
|
304
287
|
|
305
|
-
|
306
|
-
|
288
|
+
until args.empty?
|
289
|
+
field = args.shift
|
307
290
|
next unless field.is_a? Symbol
|
308
291
|
|
309
|
-
size =
|
310
|
-
|
311
|
-
else
|
312
|
-
1
|
313
|
-
end
|
292
|
+
size = size_from(args)
|
293
|
+
|
314
294
|
unless field == :_
|
315
|
-
|
316
|
-
|
317
|
-
clear_mask = (2**total_size - 1) & (~field_mask & (2**total_size - 1))
|
318
|
-
|
319
|
-
if size == 1
|
320
|
-
class_eval <<-METHODS
|
321
|
-
def #{field}?
|
322
|
-
val = (self[:#{attr}].to_i & #{field_mask}) >> #{shift}
|
323
|
-
val != 0
|
324
|
-
end
|
325
|
-
def #{field}=(v)
|
326
|
-
val = v ? 1 : 0
|
327
|
-
self[:#{attr}].value = self[:#{attr}].to_i & #{clear_mask}
|
328
|
-
self[:#{attr}].value |= val << #{shift}
|
329
|
-
end
|
330
|
-
METHODS
|
331
|
-
else
|
332
|
-
class_eval <<-METHODS
|
333
|
-
def #{field}
|
334
|
-
(self[:#{attr}].to_i & #{field_mask}) >> #{shift}
|
335
|
-
end
|
336
|
-
def #{field}=(v)
|
337
|
-
self[:#{attr}].value = self[:#{attr}].to_i & #{clear_mask}
|
338
|
-
self[:#{attr}].value |= (v & #{2**size - 1}) << #{shift}
|
339
|
-
end
|
340
|
-
METHODS
|
341
|
-
end
|
342
|
-
|
343
|
-
@bit_fields[attr] = {} if @bit_fields[attr].nil?
|
344
|
-
@bit_fields[attr][field] = size
|
295
|
+
add_bit_methods(attr, field, size, total_size, idx)
|
296
|
+
register_bit_field_size(attr, field, size)
|
345
297
|
end
|
346
298
|
|
347
299
|
idx -= size
|
348
|
-
field = args.shift
|
349
300
|
end
|
350
301
|
end
|
351
302
|
|
@@ -354,7 +305,7 @@ module PacketGen
|
|
354
305
|
# @return [void]
|
355
306
|
# @since 2.8.4
|
356
307
|
def remove_bit_fields_on(attr)
|
357
|
-
fields =
|
308
|
+
fields = bit_fields.delete(attr)
|
358
309
|
return if fields.nil?
|
359
310
|
|
360
311
|
fields.each do |field, size|
|
@@ -362,6 +313,98 @@ module PacketGen
|
|
362
313
|
undef_method(size == 1 ? "#{field}?" : field)
|
363
314
|
end
|
364
315
|
end
|
316
|
+
|
317
|
+
private
|
318
|
+
|
319
|
+
def add_methods(name, type)
|
320
|
+
define = []
|
321
|
+
if type < Types::Enum
|
322
|
+
define << "def #{name}; self[:#{name}].to_i; end"
|
323
|
+
define << "def #{name}=(val) self[:#{name}].value = val; end"
|
324
|
+
else
|
325
|
+
define << "def #{name}\n" \
|
326
|
+
" to_and_from_human?(:#{name}) ? self[:#{name}].to_human : self[:#{name}]\n" \
|
327
|
+
'end'
|
328
|
+
define << "def #{name}=(val)\n" \
|
329
|
+
" to_and_from_human?(:#{name}) ? self[:#{name}].from_human(val) : self[:#{name}].read(val)\n" \
|
330
|
+
'end'
|
331
|
+
end
|
332
|
+
|
333
|
+
define.delete_at(1) if instance_methods.include? "#{name}=".to_sym
|
334
|
+
define.delete_at(0) if instance_methods.include? name
|
335
|
+
class_eval define.join("\n")
|
336
|
+
end
|
337
|
+
|
338
|
+
def add_bit_methods(attr, name, size, total_size, idx)
|
339
|
+
shift = idx - (size - 1)
|
340
|
+
|
341
|
+
if size == 1
|
342
|
+
add_single_bit_methods(attr, name, size, total_size, shift)
|
343
|
+
else
|
344
|
+
add_multibit_methods(attr, name, size, total_size, shift)
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
def compute_field_mask(size, shift)
|
349
|
+
(2**size - 1) << shift
|
350
|
+
end
|
351
|
+
|
352
|
+
def compute_clear_mask(total_size, field_mask)
|
353
|
+
(2**total_size - 1) & (~field_mask & (2**total_size - 1))
|
354
|
+
end
|
355
|
+
|
356
|
+
def add_single_bit_methods(attr, name, size, total_size, shift)
|
357
|
+
field_mask = compute_field_mask(size, shift)
|
358
|
+
clear_mask = compute_clear_mask(total_size, field_mask)
|
359
|
+
|
360
|
+
class_eval <<-METHODS
|
361
|
+
def #{name}?
|
362
|
+
val = (self[:#{attr}].to_i & #{field_mask}) >> #{shift}
|
363
|
+
val != 0
|
364
|
+
end
|
365
|
+
def #{name}=(v)
|
366
|
+
val = v ? 1 : 0
|
367
|
+
self[:#{attr}].value = self[:#{attr}].to_i & #{clear_mask}
|
368
|
+
self[:#{attr}].value |= val << #{shift}
|
369
|
+
end
|
370
|
+
METHODS
|
371
|
+
end
|
372
|
+
|
373
|
+
def add_multibit_methods(attr, name, size, total_size, shift)
|
374
|
+
field_mask = compute_field_mask(size, shift)
|
375
|
+
clear_mask = compute_clear_mask(total_size, field_mask)
|
376
|
+
|
377
|
+
class_eval <<-METHODS
|
378
|
+
def #{name}
|
379
|
+
(self[:#{attr}].to_i & #{field_mask}) >> #{shift}
|
380
|
+
end
|
381
|
+
def #{name}=(v)
|
382
|
+
self[:#{attr}].value = self[:#{attr}].to_i & #{clear_mask}
|
383
|
+
self[:#{attr}].value |= (v & #{2**size - 1}) << #{shift}
|
384
|
+
end
|
385
|
+
METHODS
|
386
|
+
end
|
387
|
+
|
388
|
+
def register_bit_field_size(attr, field, size)
|
389
|
+
bit_fields[attr] = {} if bit_fields[attr].nil?
|
390
|
+
bit_fields[attr][field] = size
|
391
|
+
end
|
392
|
+
|
393
|
+
def field_defs_property_from(field, property, options)
|
394
|
+
field_defs[field].send("#{property}=", options.delete(property)) if options.key?(property)
|
395
|
+
end
|
396
|
+
|
397
|
+
def size_from(args)
|
398
|
+
if args.first.is_a? Integer
|
399
|
+
args.shift
|
400
|
+
else
|
401
|
+
1
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
405
|
+
def check_existence_of(field)
|
406
|
+
raise ArgumentError, "unknown #{field} field for #{self}" unless field_defs.key?(field)
|
407
|
+
end
|
365
408
|
end
|
366
409
|
|
367
410
|
# Create a new fields object
|
@@ -371,36 +414,13 @@ module PacketGen
|
|
371
414
|
@fields = {}
|
372
415
|
@optional_fields = {}
|
373
416
|
|
374
|
-
field_defs = self.class.field_defs
|
375
417
|
self.class.fields.each do |field|
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
builder = field_defs[field].builder
|
380
|
-
optional = field_defs[field].optional
|
381
|
-
enum = field_defs[field].enum
|
382
|
-
field_options = field_defs[field].options
|
383
|
-
|
384
|
-
@fields[field] = if builder
|
385
|
-
builder.call(self, type)
|
386
|
-
elsif enum
|
387
|
-
type.new(enum)
|
388
|
-
elsif !field_options.empty?
|
389
|
-
type.new(field_options)
|
390
|
-
else
|
391
|
-
type.new
|
392
|
-
end
|
393
|
-
|
394
|
-
value = options[field] || default
|
395
|
-
if value.class <= type
|
396
|
-
@fields[field] = value
|
397
|
-
elsif @fields[field].respond_to? :from_human
|
398
|
-
@fields[field].from_human(value)
|
399
|
-
end
|
400
|
-
|
401
|
-
@optional_fields[field] = optional if optional
|
418
|
+
build_field field
|
419
|
+
initialize_value field, options[field]
|
420
|
+
initialize_optional field
|
402
421
|
end
|
403
|
-
|
422
|
+
|
423
|
+
self.class.bit_fields.each do |_, hsh|
|
404
424
|
hsh.each_key do |bit_field|
|
405
425
|
self.send "#{bit_field}=", options[bit_field] if options[bit_field]
|
406
426
|
end
|
@@ -409,7 +429,7 @@ module PacketGen
|
|
409
429
|
|
410
430
|
# Get field object
|
411
431
|
# @param [Symbol] field
|
412
|
-
# @return [
|
432
|
+
# @return [Fieldable]
|
413
433
|
def [](field)
|
414
434
|
@fields[field]
|
415
435
|
end
|
@@ -429,6 +449,7 @@ module PacketGen
|
|
429
449
|
end
|
430
450
|
|
431
451
|
# Get all optional field name
|
452
|
+
# @return[Array<Symbol>,nil]
|
432
453
|
def optional_fields
|
433
454
|
@optional_fields.keys
|
434
455
|
end
|
@@ -459,11 +480,7 @@ module PacketGen
|
|
459
480
|
next unless present?(field)
|
460
481
|
|
461
482
|
obj = self[field].read str[start..-1]
|
462
|
-
|
463
|
-
start += self[field].sz
|
464
|
-
else
|
465
|
-
start = str.size
|
466
|
-
end
|
483
|
+
start += self[field].sz
|
467
484
|
self[field] = obj unless obj == self[field]
|
468
485
|
end
|
469
486
|
|
@@ -530,7 +547,7 @@ module PacketGen
|
|
530
547
|
# @return [Hash,nil] keys: bit fields, values: their size in bits
|
531
548
|
# @since 2.8.3
|
532
549
|
def bits_on(field)
|
533
|
-
self.class.
|
550
|
+
self.class.bit_fields[field]
|
534
551
|
end
|
535
552
|
|
536
553
|
private
|
@@ -549,6 +566,54 @@ module PacketGen
|
|
549
566
|
def force_binary(str)
|
550
567
|
PacketGen.force_binary(str)
|
551
568
|
end
|
569
|
+
|
570
|
+
# @param [Symbol] attr attribute
|
571
|
+
# @return [Boolean] +tru+e if #from_human and #to_human are both defined for given attribute
|
572
|
+
def to_and_from_human?(attr)
|
573
|
+
self[attr].respond_to?(:to_human) && self[attr].respond_to?(:from_human)
|
574
|
+
end
|
575
|
+
|
576
|
+
def field_defs
|
577
|
+
self.class.field_defs
|
578
|
+
end
|
579
|
+
|
580
|
+
# rubocop:disable Metrics/AbcSize
|
581
|
+
def build_field(field)
|
582
|
+
type = field_defs[field].type
|
583
|
+
|
584
|
+
@fields[field] = if field_defs[field].builder
|
585
|
+
field_defs[field].builder.call(self, type)
|
586
|
+
elsif field_defs[field].enum
|
587
|
+
type.new(field_defs[field].enum)
|
588
|
+
elsif !field_defs[field].options.empty?
|
589
|
+
type.new(field_defs[field].options)
|
590
|
+
else
|
591
|
+
type.new
|
592
|
+
end
|
593
|
+
end
|
594
|
+
# rubocop:enable Metrics/AbcSize
|
595
|
+
|
596
|
+
def initialize_value(field, val)
|
597
|
+
type = field_defs[field].type
|
598
|
+
default = field_defs[field].default
|
599
|
+
default = default.to_proc.call(self) if default.is_a?(Proc)
|
600
|
+
|
601
|
+
value = val || default
|
602
|
+
if value.class <= type
|
603
|
+
@fields[field] = value
|
604
|
+
elsif @fields[field].respond_to? :from_human
|
605
|
+
@fields[field].from_human(value)
|
606
|
+
else
|
607
|
+
@fields[field].read(value)
|
608
|
+
end
|
609
|
+
end
|
610
|
+
|
611
|
+
def initialize_optional(field)
|
612
|
+
optional = field_defs[field].optional
|
613
|
+
@optional_fields[field] = optional if optional
|
614
|
+
end
|
552
615
|
end
|
553
616
|
end
|
554
617
|
end
|
618
|
+
|
619
|
+
# rubocop:enable Metrics/ClassLength
|
data/lib/packetgen/types/int.rb
CHANGED
@@ -1,17 +1,19 @@
|
|
1
1
|
# coding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
2
4
|
# This file is part of PacketGen
|
3
5
|
# See https://github.com/sdaubert/packetgen for more informations
|
4
6
|
# Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
|
5
7
|
# This program is published under MIT license.
|
6
8
|
|
7
|
-
# frozen_string_literal: true
|
8
|
-
|
9
9
|
module PacketGen
|
10
10
|
module Types
|
11
11
|
# Base integer class to handle binary integers
|
12
12
|
# @abstract
|
13
13
|
# @author Sylvain Daubert
|
14
14
|
class Int
|
15
|
+
include Fieldable
|
16
|
+
|
15
17
|
# Integer value
|
16
18
|
# @return [Integer]
|
17
19
|
attr_accessor :value
|
@@ -45,7 +47,7 @@ module PacketGen
|
|
45
47
|
@value = if value.is_a?(Integer)
|
46
48
|
value.to_i
|
47
49
|
elsif defined? @packstr
|
48
|
-
value.to_s.
|
50
|
+
value.to_s.unpack1(@packstr[@endian])
|
49
51
|
else
|
50
52
|
raise ParseError, 'Int#read is abstract and cannot read'
|
51
53
|
end
|
@@ -56,9 +58,7 @@ module PacketGen
|
|
56
58
|
# @return [::String]
|
57
59
|
# @raise [ParseError] This is an abstrat method and must be redefined
|
58
60
|
def to_s
|
59
|
-
unless defined? @packstr
|
60
|
-
raise ParseError, 'PacketGen::Types::Int#to_s is an abstract method'
|
61
|
-
end
|
61
|
+
raise ParseError, 'PacketGen::Types::Int#to_s is an abstract method' unless defined? @packstr
|
62
62
|
|
63
63
|
[to_i].pack(@packstr[@endian])
|
64
64
|
end
|
@@ -82,6 +82,18 @@ module PacketGen
|
|
82
82
|
def sz
|
83
83
|
width
|
84
84
|
end
|
85
|
+
|
86
|
+
# Format Int type when inspecting header or packet
|
87
|
+
# @return [String]
|
88
|
+
def format_inspect
|
89
|
+
format_str % [to_i.to_s, to_i]
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def format_str
|
95
|
+
"%-16s (0x%0#{width * 2}x)"
|
96
|
+
end
|
85
97
|
end
|
86
98
|
|
87
99
|
# One byte unsigned integer
|