packetgen 3.3.3 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +37 -21
  3. data/lib/packetgen/capture.rb +2 -2
  4. data/lib/packetgen/config.rb +0 -1
  5. data/lib/packetgen/deprecation.rb +7 -7
  6. data/lib/packetgen/header/arp.rb +13 -13
  7. data/lib/packetgen/header/asn1_base.rb +1 -1
  8. data/lib/packetgen/header/base.rb +17 -18
  9. data/lib/packetgen/header/bootp.rb +32 -34
  10. data/lib/packetgen/header/dhcp/option.rb +19 -19
  11. data/lib/packetgen/header/dhcp/options.rb +1 -1
  12. data/lib/packetgen/header/dhcp.rb +3 -3
  13. data/lib/packetgen/header/dhcpv6/duid.rb +16 -16
  14. data/lib/packetgen/header/dhcpv6/option.rb +53 -53
  15. data/lib/packetgen/header/dhcpv6/options.rb +1 -1
  16. data/lib/packetgen/header/dhcpv6/relay.rb +5 -5
  17. data/lib/packetgen/header/dhcpv6.rb +6 -6
  18. data/lib/packetgen/header/dns/name.rb +14 -10
  19. data/lib/packetgen/header/dns/opt.rb +2 -2
  20. data/lib/packetgen/header/dns/option.rb +11 -11
  21. data/lib/packetgen/header/dns/qdsection.rb +1 -1
  22. data/lib/packetgen/header/dns/question.rb +6 -8
  23. data/lib/packetgen/header/dns/rr.rb +56 -43
  24. data/lib/packetgen/header/dns/rrsection.rb +4 -4
  25. data/lib/packetgen/header/dns.rb +27 -30
  26. data/lib/packetgen/header/dot11/control.rb +11 -11
  27. data/lib/packetgen/header/dot11/data.rb +20 -20
  28. data/lib/packetgen/header/dot11/element.rb +4 -4
  29. data/lib/packetgen/header/dot11/management.rb +8 -8
  30. data/lib/packetgen/header/dot11/sub_mngt.rb +39 -53
  31. data/lib/packetgen/header/dot11.rb +88 -93
  32. data/lib/packetgen/header/dot1q.rb +10 -12
  33. data/lib/packetgen/header/dot1x.rb +9 -9
  34. data/lib/packetgen/header/eap/fast.rb +4 -4
  35. data/lib/packetgen/header/eap/md5.rb +6 -6
  36. data/lib/packetgen/header/eap/tls.rb +13 -15
  37. data/lib/packetgen/header/eap/ttls.rb +13 -15
  38. data/lib/packetgen/header/eap.rb +22 -22
  39. data/lib/packetgen/header/eth.rb +18 -18
  40. data/lib/packetgen/header/gre.rb +8 -10
  41. data/lib/packetgen/header/http/headers.rb +2 -2
  42. data/lib/packetgen/header/http/request.rb +17 -16
  43. data/lib/packetgen/header/http/response.rb +18 -17
  44. data/lib/packetgen/header/http/verbs.rb +1 -3
  45. data/lib/packetgen/header/icmp.rb +8 -8
  46. data/lib/packetgen/header/icmpv6.rb +3 -3
  47. data/lib/packetgen/header/igmp.rb +8 -8
  48. data/lib/packetgen/header/igmpv3/group_record.rb +12 -12
  49. data/lib/packetgen/header/igmpv3/mq.rb +16 -18
  50. data/lib/packetgen/header/igmpv3/mr.rb +4 -4
  51. data/lib/packetgen/header/igmpv3.rb +7 -7
  52. data/lib/packetgen/header/ip/addr.rb +13 -13
  53. data/lib/packetgen/header/ip/option.rb +31 -33
  54. data/lib/packetgen/header/ip/options.rb +1 -1
  55. data/lib/packetgen/header/ip.rb +37 -72
  56. data/lib/packetgen/header/ipv6/addr.rb +14 -14
  57. data/lib/packetgen/header/ipv6/extension.rb +8 -8
  58. data/lib/packetgen/header/ipv6/hop_by_hop.rb +9 -9
  59. data/lib/packetgen/header/ipv6.rb +20 -22
  60. data/lib/packetgen/header/llc.rb +17 -17
  61. data/lib/packetgen/header/mdns.rb +1 -1
  62. data/lib/packetgen/header/mld.rb +6 -6
  63. data/lib/packetgen/header/mldv2/mcast_address_record.rb +11 -11
  64. data/lib/packetgen/header/mldv2/mlq.rb +21 -23
  65. data/lib/packetgen/header/mldv2/mlr.rb +8 -8
  66. data/lib/packetgen/header/ospfv2/db_description.rb +11 -12
  67. data/lib/packetgen/header/ospfv2/hello.rb +11 -11
  68. data/lib/packetgen/header/ospfv2/ls_ack.rb +1 -1
  69. data/lib/packetgen/header/ospfv2/ls_request.rb +9 -9
  70. data/lib/packetgen/header/ospfv2/ls_update.rb +3 -3
  71. data/lib/packetgen/header/ospfv2/lsa.rb +54 -58
  72. data/lib/packetgen/header/ospfv2/lsa_header.rb +9 -9
  73. data/lib/packetgen/header/ospfv2.rb +27 -29
  74. data/lib/packetgen/header/ospfv3/db_description.rb +13 -14
  75. data/lib/packetgen/header/ospfv3/hello.rb +12 -12
  76. data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +17 -19
  77. data/lib/packetgen/header/ospfv3/ls_ack.rb +2 -2
  78. data/lib/packetgen/header/ospfv3/ls_request.rb +9 -9
  79. data/lib/packetgen/header/ospfv3/ls_update.rb +4 -4
  80. data/lib/packetgen/header/ospfv3/lsa.rb +48 -51
  81. data/lib/packetgen/header/ospfv3/lsa_header.rb +9 -9
  82. data/lib/packetgen/header/ospfv3.rb +25 -27
  83. data/lib/packetgen/header/sctp/chunk.rb +44 -41
  84. data/lib/packetgen/header/sctp/error.rb +52 -52
  85. data/lib/packetgen/header/sctp/parameter.rb +38 -38
  86. data/lib/packetgen/header/sctp.rb +5 -5
  87. data/lib/packetgen/header/snmp.rb +2 -2
  88. data/lib/packetgen/header/tcp/option.rb +45 -39
  89. data/lib/packetgen/header/tcp/options.rb +2 -2
  90. data/lib/packetgen/header/tcp.rb +55 -44
  91. data/lib/packetgen/header/tftp.rb +16 -16
  92. data/lib/packetgen/header/udp.rb +8 -8
  93. data/lib/packetgen/header.rb +9 -10
  94. data/lib/packetgen/headerable.rb +13 -3
  95. data/lib/packetgen/inspect.rb +2 -2
  96. data/lib/packetgen/packet.rb +54 -37
  97. data/lib/packetgen/pcap.rb +15 -4
  98. data/lib/packetgen/pcapng/block.rb +18 -17
  99. data/lib/packetgen/pcapng/epb.rb +13 -15
  100. data/lib/packetgen/pcapng/file.rb +3 -97
  101. data/lib/packetgen/pcapng/idb.rb +9 -11
  102. data/lib/packetgen/pcapng/shb.rb +13 -15
  103. data/lib/packetgen/pcapng/spb.rb +8 -10
  104. data/lib/packetgen/pcapng/unknown_block.rb +6 -17
  105. data/lib/packetgen/pcapng.rb +4 -4
  106. data/lib/packetgen/pcaprub_wrapper.rb +17 -1
  107. data/lib/packetgen/proto.rb +1 -1
  108. data/lib/packetgen/unknown_packet.rb +2 -2
  109. data/lib/packetgen/utils/arp_spoofer.rb +18 -19
  110. data/lib/packetgen/utils.rb +2 -2
  111. data/lib/packetgen/version.rb +1 -1
  112. data/lib/packetgen.rb +4 -3
  113. metadata +29 -38
  114. data/lib/packetgen/types/abstract_tlv.rb +0 -278
  115. data/lib/packetgen/types/array.rb +0 -287
  116. data/lib/packetgen/types/cstring.rb +0 -109
  117. data/lib/packetgen/types/enum.rb +0 -171
  118. data/lib/packetgen/types/fieldable.rb +0 -66
  119. data/lib/packetgen/types/fields.rb +0 -622
  120. data/lib/packetgen/types/int.rb +0 -473
  121. data/lib/packetgen/types/int_string.rb +0 -102
  122. data/lib/packetgen/types/length_from.rb +0 -54
  123. data/lib/packetgen/types/oui.rb +0 -52
  124. data/lib/packetgen/types/string.rb +0 -97
  125. data/lib/packetgen/types/tlv.rb +0 -161
  126. data/lib/packetgen/types.rb +0 -26
@@ -1,278 +0,0 @@
1
- # coding: utf-8
2
- # frozen_string_literal: true
3
-
4
- # This file is part of PacketGen
5
- # See https://github.com/lemontree55/packetgen for more informations
6
- # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
7
- # Copyright (C) 2024 LemonTree55 <lenontree@proton.me>
8
- # This program is published under MIT license.
9
-
10
- module PacketGen
11
- module Types
12
- # This class is an abstract class to define type-length-value data.
13
- #
14
- # This class supersedes {TLV} class, which is not well defined on some corner
15
- # cases.
16
- #
17
- # ===Usage
18
- # To simply define a new TLV class, do:
19
- # MyTLV = PacketGen::Types::AbstractTLV.create
20
- # MyTLV.define_type_enum 'one' => 1, 'two' => 2
21
- # This will define a new +MyTLV+ class, subclass of {Fields}. This class will
22
- # define 3 fields:
23
- # * +#type+, as a {Int8Enum} by default,
24
- # * +#length+, as a {Int8} by default,
25
- # * and +#value+, as a {String} by default.
26
- # +.define_type_enum+ is, here, necessary to define enum hash to be used
27
- # for +#type+ accessor, as this one is defined as an {Enum}.
28
- #
29
- # This class may then be used as older {TLV} class:
30
- # tlv = MyTLV.new(type: 1, value: 'abcd') # automagically set #length from value
31
- # tlv.type #=> 1
32
- # tlv.human_type #=> 'one'
33
- # tlv.length #=> 4
34
- # tlv.value #=> "abcd"
35
- #
36
- # ===Advanced usage
37
- # Each field's type may be changed at generating TLV class:
38
- # MyTLV = PacketGen::Types::AbstractTLV.create(type_class: PacketGen::Types::Int16,
39
- # length_class: PacketGen::Types::Int16,
40
- # value_class: PacketGen::Header::IP::Addr)
41
- # tlv = MyTLV.new(type: 1, value: '1.2.3.4')
42
- # tlv.type #=> 1
43
- # tlv.length #=> 4
44
- # tlv.value #=> '1.2.3.4'
45
- # tlv.to_s #=> "\x00\x01\x00\x04\x01\x02\x03\x04"
46
- #
47
- # Some aliases may also be defined. For example, to create a TLV type
48
- # whose +type+ field should be named +code+:
49
- # MyTLV = PacketGen::Types::AbstractTLV.create(type_class: PacketGen::Types::Int16,
50
- # length_class: PacketGen::Types::Int16,
51
- # aliases: { code: :type })
52
- # tlv = MyTLV.new(code: 1, value: 'abcd')
53
- # tlv.code #=> 1
54
- # tlv.type #=> 1
55
- # tlv.length #=> 4
56
- # tlv.value #=> 'abcd'
57
- #
58
- # @author Sylvain Daubert
59
- # @since 3.1.0
60
- # @since 3.1.1 add +:aliases+ keyword to {#initialize}
61
- class AbstractTLV < Types::Fields
62
- include Fieldable
63
-
64
- # @private
65
- FIELD_TYPES = { 'T' => :type, 'L' => :length, 'V' => :value }.freeze
66
-
67
- class << self
68
- # @return [Hash]
69
- attr_accessor :aliases
70
- # @deprecated
71
- attr_accessor :header_in_length
72
- # @private
73
- attr_accessor :field_in_length
74
-
75
- # rubocop:disable Metrics/ParameterLists
76
-
77
- # Generate a TLV class
78
- # @param [Class] type_class Class to use for +type+
79
- # @param [Class] length_class Class to use for +length+
80
- # @param [Class] value_class Class to use for +value+
81
- # @param [Boolean] header_in_length if +true +, +type+ and +length+ fields are
82
- # included in length. Deprecated, use +field_in_length+ instead.
83
- # @param [String] field_order give field order. Each character in [T,L,V] MUST be present once, in the desired order.
84
- # @param [String] field_in_length give fields to compute length on.
85
- # @return [Class]
86
- # @since 3.1.4 Add +header_in_length+ parameter
87
- # @since 3.3.1 Add +field_order+ and +field_in_length' parameters. Deprecate +header_in_length+ parameter.
88
- def create(type_class: Int8Enum, length_class: Int8, value_class: String,
89
- aliases: {}, header_in_length: false, field_order: 'TLV', field_in_length: 'V')
90
- Deprecation.deprecated_option(self, 'create', 'header_in_length', klass_method: true) if header_in_length
91
- raise Error, '.create cannot be called on a subclass of PacketGen::Types::AbstractTLV' unless self.equal?(AbstractTLV)
92
-
93
- klass = Class.new(self)
94
- klass.aliases = aliases
95
- klass.header_in_length = header_in_length
96
- klass.field_in_length = field_in_length
97
-
98
- check_field_in_length(field_in_length)
99
- check_field_order(field_order)
100
- generate_fields(klass, field_order, type_class, length_class, value_class)
101
-
102
- aliases.each do |al, orig|
103
- klass.instance_eval do
104
- alias_method al, orig if klass.method_defined?(orig)
105
- alias_method :"#{al}=", :"#{orig}=" if klass.method_defined?(:"#{orig}=")
106
- end
107
- end
108
-
109
- klass
110
- end
111
- # rubocop:enable Metrics/ParameterLists
112
-
113
- # @!attribute type
114
- # @abstract Type attribute for real TLV class
115
- # @return [Integer]
116
- # @!attribute length
117
- # @abstract Length attribute for real TLV class
118
- # @return [Integer]
119
- # @!attribute value
120
- # @abstract Value attribute for real TLV class
121
- # @return [Object]
122
-
123
- # @abstract Should only be called on real TLV classes, created by {.create}.
124
- # Set enum hash for {#type} field.
125
- # @param [Hash{String, Symbol => Integer}] hsh enum hash
126
- # @return [void]
127
- def define_type_enum(hsh)
128
- field_defs[:type][:enum].clear
129
- field_defs[:type][:enum].merge!(hsh)
130
- end
131
-
132
- # @abstract Should only be called on real TLV classes, created by {.create}.
133
- # Set default value for {#type} field.
134
- # @param [Integer,String,Symbol,nil] default default value from +hsh+ for type
135
- # @return [void]
136
- # @since 3.4.0
137
- def define_type_default(default)
138
- field_defs[:type][:default] = default
139
- end
140
-
141
- private
142
-
143
- def check_field_in_length(field_in_length)
144
- return if /^[TLV]{1,3}$/.match?(field_in_length)
145
-
146
- raise 'field_in_length must only contain T, L and/or V characters'
147
- end
148
-
149
- def check_field_order(field_order)
150
- return if field_order.match(/^[TLV]{3,3}$/) && (field_order[0] != field_order[1]) && (field_order[0] != field_order[2]) && (field_order[1] != field_order[2])
151
-
152
- raise 'field_order must contain all three letters TLV, each once'
153
- end
154
-
155
- def generate_fields(klass, field_order, type_class, length_class, value_class)
156
- field_order.each_char do |field_type|
157
- case field_type
158
- when 'T'
159
- if type_class < Enum
160
- klass.define_field(:type, type_class, enum: {})
161
- else
162
- klass.define_field(:type, type_class)
163
- end
164
- when 'L'
165
- klass.define_field(:length, length_class)
166
- when 'V'
167
- klass.define_field(:value, value_class)
168
- end
169
- end
170
- end
171
- end
172
-
173
- # @!attribute type
174
- # @abstract Type attribute
175
- # @return [Integer]
176
- # @!attribute length
177
- # @abstract Length
178
- # @return [Integer]
179
- # @!attribute value
180
- # @abstract Value attribute
181
- # @return [Object]
182
-
183
- # @abstract Should only be called on real TLV classes, created by {.create}.
184
- # @param [Hash] options
185
- # @option options [Integer] :type
186
- # @option options [Integer] :length
187
- # @option options [Object] :value
188
- def initialize(options={})
189
- @header_in_length = self.class.header_in_length
190
- @field_in_length = self.class.field_in_length
191
- self.class.aliases.each do |al, orig|
192
- options[orig] = options[al] if options.key?(al)
193
- end
194
-
195
- super
196
- # used #value= defined below, which set length if needed
197
- self.value = options[:value] if options[:value]
198
- calc_length unless options.key?(:length)
199
- end
200
-
201
- # @abstract Should only be called on real TLV class instances.
202
- # Populate object from a binary string
203
- # @param [String,nil] str
204
- # @return [Fields] self
205
- def read(str)
206
- return self if str.nil?
207
-
208
- idx = 0
209
- fields.each do |field_name|
210
- field = self[field_name]
211
- length = field_name == :value ? real_length : field.sz
212
- field.read(str[idx, length])
213
- idx += field.sz
214
- end
215
-
216
- self
217
- end
218
-
219
- # @abstract Should only be called on real TLV class instances.
220
- # Set +value+. May set +length+ if value is a {Types::String}.
221
- # @param [Object] val
222
- # @return [Object]
223
- # @since 3.4.0 Base on field's +#from_human+ method
224
- def value=(val)
225
- if val.is_a?(self[:value].class)
226
- self[:value] = val
227
- elsif self[:value].respond_to?(:from_human)
228
- self[:value].from_human(val)
229
- else
230
- self[:value].read(val)
231
- end
232
- calc_length
233
- val
234
- end
235
-
236
- # @abstract Should only be called on real TLV class instances.
237
- # Get human-readable type
238
- # @return [String]
239
- def human_type
240
- self[:type].to_human.to_s
241
- end
242
-
243
- # @abstract Should only be called on real TLV class instances.
244
- # @return [String]
245
- def to_human
246
- my_value = self[:value].is_a?(String) ? self[:value].inspect : self[:value].to_human
247
- 'type:%s,length:%u,value:%s' % [human_type, length, my_value]
248
- end
249
-
250
- # Calculate length
251
- # @return [void]
252
- # @since 3.4.0
253
- def calc_length
254
- fil = @field_in_length
255
- fil = 'TLV' if @header_in_length
256
-
257
- length = 0
258
- fil.each_char do |field_type|
259
- length += self[FIELD_TYPES[field_type]].sz
260
- end
261
- self.length = length
262
- end
263
-
264
- private
265
-
266
- def real_length
267
- if @header_in_length
268
- self.length - self[:type].sz - self[:length].sz
269
- else
270
- length = self.length
271
- length -= self[:type].sz if @field_in_length.include?('T')
272
- length -= self[:length].sz if @field_in_length.include?('L')
273
- length
274
- end
275
- end
276
- end
277
- end
278
- end
@@ -1,287 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # This file is part of PacketGen
4
- # See https://github.com/lemontree55/packetgen for more informations
5
- # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
6
- # Copyright (C) 2024 LemonTree55 <lenontree@proton.me>
7
- # This program is published under MIT license.
8
-
9
- require 'forwardable'
10
-
11
- module PacketGen
12
- module Types
13
- # @abstract Base class to define set of {Fields} subclasses.
14
- # == #record_from_hash
15
- # Subclasses should define private method +#record_from_hash+. This method
16
- # is called by {#push} to add an object to the set.
17
- #
18
- # A default method is defined by {Array}: it calls constructor of class defined
19
- # by {.set_of}.
20
- #
21
- # == #real_type
22
- # Subclasses should define private method +#real_type+ if {.set_of} type
23
- # may be subclassed. This method should return real class to use. It
24
- # takes an only argument, which is of type given by {.set_of}.
25
- #
26
- # Default behaviour of this method is to return argument's class.
27
- #
28
- # @author Sylvain Daubert
29
- class Array
30
- extend Forwardable
31
- include Enumerable
32
- include Fieldable
33
- include LengthFrom
34
-
35
- # @!method [](index)
36
- # Return the element at +index+.
37
- # @param [integer] index
38
- # @return [Object]
39
- # @!method clear
40
- # Clear array.
41
- # @return [void]
42
- # @!method each
43
- # Calls the given block once for each element in self, passing that
44
- # element as a parameter. Returns the array itself.
45
- # @return [Array]
46
- # @method empty?
47
- # Return +true+ if contains no element.
48
- # @return [Booelan]
49
- # @!method first
50
- # Return first element
51
- # @return [Object]
52
- # @!method last
53
- # Return last element.
54
- # @return [Object]
55
- # @!method size
56
- # Get number of element in array
57
- # @return [Integer]
58
- def_delegators :@array, :[], :clear, :each, :empty?, :first, :last, :size
59
- alias length size
60
-
61
- # Separator used in {#to_human}.
62
- # May be ovverriden by subclasses
63
- HUMAN_SEPARATOR = ','
64
-
65
- # rubocop:disable Naming/AccessorMethodName
66
- class << self
67
- # Get class set with {.set_of}.
68
- # @return [Class]
69
- # @since 3.0.0
70
- def set_of_klass
71
- @klass
72
- end
73
-
74
- # Define type of objects in set. Used by {#read} and {#push}.
75
- # @param [Class] klass
76
- # @return [void]
77
- def set_of(klass)
78
- @klass = klass
79
- end
80
- end
81
- # rubocop:enable Naming/AccessorMethodName
82
-
83
- # @param [Hash] options
84
- # @option options [Int] counter Int object used as a counter for this set
85
- def initialize(options={})
86
- @counter = options[:counter]
87
- @array = []
88
- initialize_length_from(options)
89
- end
90
-
91
- # Initialize array for copy:
92
- # * duplicate internal array.
93
- def initialize_copy(_other)
94
- @array = @array.dup
95
- end
96
-
97
- def ==(other)
98
- @array == case other
99
- when Array
100
- other.to_a
101
- else
102
- other
103
- end
104
- end
105
-
106
- # Clear array. Reset associated counter, if any.
107
- # @return [void]
108
- def clear!
109
- @array.clear
110
- @counter&.read(0)
111
- end
112
-
113
- # Delete an object from this array. Update associated counter if any
114
- # @param [Object] obj
115
- # @return [Object] deleted object
116
- def delete(obj)
117
- deleted = @array.delete(obj)
118
- @counter.read(@counter.to_i - 1) if @counter && deleted
119
- deleted
120
- end
121
-
122
- # Delete element at +index+.
123
- # @param [Integer] index
124
- # @return [Object,nil] deleted object
125
- def delete_at(index)
126
- deleted = @array.delete_at(index)
127
- @counter.read(@counter.to_i - 1) if @counter && deleted
128
- deleted
129
- end
130
-
131
- # @abstract depend on private method +#record_from_hash+ which should be
132
- # declared by subclasses.
133
- # Add an object to this array
134
- # @param [Object] obj type depends on subclass
135
- # @return [Array] self
136
- def push(obj)
137
- obj = case obj
138
- when Hash
139
- record_from_hash obj
140
- else
141
- obj
142
- end
143
- @array << obj
144
- self
145
- end
146
-
147
- # @abstract depend on private method +#record_from_hash+ which should be
148
- # declared by subclasses.
149
- # Add an object to this array, and increment associated counter, if any
150
- # @param [Object] obj type depends on subclass
151
- # @return [Array] self
152
- def <<(obj)
153
- push obj
154
- @counter&.read(@counter.to_i + 1)
155
- self
156
- end
157
-
158
- # Populate object from a string or from an array of hashes
159
- # @param [String, Array<Hash>] data
160
- # @return [self]
161
- def read(data)
162
- clear
163
- case data
164
- when ::Array
165
- read_from_array(data)
166
- else
167
- read_from_string(data)
168
- end
169
- self
170
- end
171
-
172
- # Get size in bytes
173
- # @return [Integer]
174
- def sz
175
- to_s.size
176
- end
177
-
178
- # Return an Array
179
- # @return [::Array]
180
- def to_a
181
- @array
182
- end
183
-
184
- # Get binary string
185
- # @return [String]
186
- def to_s
187
- @array.map(&:to_s).join
188
- end
189
-
190
- # Get a human readable string
191
- # @return [String]
192
- def to_human
193
- @array.map(&:to_human).join(self.class::HUMAN_SEPARATOR)
194
- end
195
-
196
- private
197
-
198
- # rubocop:disable Metrics/CyclomaticComplexity
199
-
200
- def read_from_string(str)
201
- return self if str.nil? || @counter&.to_i&.zero?
202
-
203
- str = read_with_length_from(str)
204
- until str.empty? || (@counter && self.size == @counter.to_i)
205
- obj = create_object_from_str(str)
206
- @array << obj
207
- str.slice!(0, obj.sz)
208
- end
209
- end
210
- # rubocop:enable Metrics/CyclomaticComplexity
211
-
212
- def read_from_array(ary)
213
- return self if ary.empty?
214
-
215
- ary.each do |hsh|
216
- self << hsh
217
- end
218
- end
219
-
220
- def record_from_hash(hsh)
221
- obj_klass = self.class.set_of_klass
222
- raise NotImplementedError, 'class should define #record_from_hash or declare type of elements in set with .set_of' unless obj_klass
223
-
224
- obj = obj_klass.new(hsh) if obj_klass
225
- klass = real_type(obj)
226
- klass == obj_klass ? obj : klass.new(hsh)
227
- end
228
-
229
- def real_type(_obj)
230
- self.class.set_of_klass
231
- end
232
-
233
- def create_object_from_str(str)
234
- klass = self.class.set_of_klass
235
- obj = klass.new.read(str)
236
- real_klass = real_type(obj)
237
-
238
- if real_klass == klass
239
- obj
240
- else
241
- real_klass.new.read(str)
242
- end
243
- end
244
- end
245
-
246
- # @private
247
- module ArrayOfIntMixin
248
- def read_from_array(ary)
249
- return self if ary.empty?
250
-
251
- ary.each do |i|
252
- self << self.class.set_of_klass.new(i)
253
- end
254
- end
255
- end
256
-
257
- # Specialized array to handle serie of {Int8}.
258
- class ArrayOfInt8 < Array
259
- include ArrayOfIntMixin
260
- set_of Int8
261
- end
262
-
263
- # Specialized array to handle serie of {Int16}.
264
- class ArrayOfInt16 < Array
265
- include ArrayOfIntMixin
266
- set_of Int16
267
- end
268
-
269
- # Specialized array to handle serie of {Int16le}.
270
- class ArrayOfInt16le < Array
271
- include ArrayOfIntMixin
272
- set_of Int16le
273
- end
274
-
275
- # Specialized array to handle serie of {Int32}.
276
- class ArrayOfInt32 < Types::Array
277
- include ArrayOfIntMixin
278
- set_of Types::Int32
279
- end
280
-
281
- # Specialized array to handle serie of {Int32le}.
282
- class ArrayOfInt32le < Types::Array
283
- include ArrayOfIntMixin
284
- set_of Types::Int32le
285
- end
286
- end
287
- end
@@ -1,109 +0,0 @@
1
- # coding: utf-8
2
- # frozen_string_literal: true
3
-
4
- # This file is part of PacketGen
5
- # See https://github.com/lemontree55/packetgen for more informations
6
- # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
7
- # Copyright (C) 2024 LemonTree55 <lenontree@proton.me>
8
- # This program is published under MIT license.
9
-
10
- require 'forwardable'
11
-
12
- module PacketGen
13
- module Types
14
- # This class handles null-terminated strings (aka C strings).
15
- # @author Sylvain Daubert
16
- # @since 3.1.6 no more a subclass or regular String
17
- class CString
18
- extend Forwardable
19
- include Fieldable
20
-
21
- def_delegators :@string, :[], :length, :size, :inspect, :==,
22
- :unpack, :force_encoding, :encoding, :index, :empty?,
23
- :encode, :slice, :slice!
24
-
25
- # @return [::String]
26
- attr_reader :string
27
- # @return [Integer]
28
- attr_reader :static_length
29
-
30
- # @param [Hash] options
31
- # @option options [Integer] :static_length set a static length for this string
32
- def initialize(options={})
33
- register_internal_string(+'')
34
- @static_length = options[:static_length]
35
- end
36
-
37
- # @param [::String] str
38
- # @return [String] self
39
- def read(str)
40
- s = str.to_s
41
- s = s[0, static_length] if static_length?
42
- register_internal_string s
43
- remove_null_character
44
- self
45
- end
46
-
47
- # get null-terminated string
48
- # @return [String]
49
- def to_s
50
- if static_length?
51
- s = string[0, static_length - 1]
52
- s << "\x00" * (static_length - s.length)
53
- else
54
- s = "#{string}\x00"
55
- end
56
- PacketGen.force_binary(s)
57
- end
58
-
59
- # Append the given string to CString
60
- # @param [#to_s] str
61
- # @return [self]
62
- def <<(str)
63
- @string << str.to_s
64
- remove_null_character
65
- self
66
- end
67
-
68
- # @return [Integer]
69
- def sz
70
- if static_length?
71
- static_length
72
- else
73
- to_s.size
74
- end
75
- end
76
-
77
- # Say if a static length is defined
78
- # @return [Boolean]
79
- # @since 3.1.6
80
- def static_length?
81
- !static_length.nil?
82
- end
83
-
84
- # Populate CString from a human readable string
85
- # @param [String] str
86
- # @return [self]
87
- def from_human(str)
88
- read str
89
- end
90
-
91
- # @return [String]
92
- def to_human
93
- string
94
- end
95
-
96
- private
97
-
98
- def register_internal_string(str)
99
- @string = str
100
- PacketGen.force_binary(@string)
101
- end
102
-
103
- def remove_null_character
104
- idx = string.index(0.chr)
105
- register_internal_string(string[0, idx]) unless idx.nil?
106
- end
107
- end
108
- end
109
- end