packetgen 3.1.4 → 3.2.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/README.md +0 -1
- data/bin/pgconsole +1 -0
- data/lib/packetgen.rb +19 -3
- data/lib/packetgen/capture.rb +30 -9
- data/lib/packetgen/config.rb +15 -9
- data/lib/packetgen/deprecation.rb +1 -1
- data/lib/packetgen/header/asn1_base.rb +19 -9
- data/lib/packetgen/header/base.rb +68 -70
- data/lib/packetgen/header/dhcpv6/duid.rb +3 -1
- data/lib/packetgen/header/dhcpv6/option.rb +4 -12
- data/lib/packetgen/header/dns/name.rb +18 -7
- data/lib/packetgen/header/dns/qdsection.rb +1 -1
- data/lib/packetgen/header/dns/question.rb +2 -0
- data/lib/packetgen/header/dot11.rb +25 -38
- data/lib/packetgen/header/dot11/data.rb +28 -34
- data/lib/packetgen/header/dot1x.rb +1 -14
- data/lib/packetgen/header/eap.rb +14 -17
- data/lib/packetgen/header/eth.rb +5 -6
- data/lib/packetgen/header/http/headers.rb +4 -2
- data/lib/packetgen/header/http/request.rb +37 -18
- data/lib/packetgen/header/http/response.rb +11 -5
- data/lib/packetgen/header/http/verbs.rb +1 -1
- data/lib/packetgen/header/igmpv3/group_record.rb +2 -0
- data/lib/packetgen/header/ip.rb +27 -26
- data/lib/packetgen/header/ip/addr.rb +3 -1
- data/lib/packetgen/header/ip/option.rb +4 -4
- data/lib/packetgen/header/ipv6/addr.rb +2 -0
- data/lib/packetgen/header/mldv2/mcast_address_record.rb +2 -0
- data/lib/packetgen/header/ospfv2/ls_request.rb +2 -0
- data/lib/packetgen/header/ospfv2/lsa.rb +13 -3
- data/lib/packetgen/header/ospfv2/lsa_header.rb +2 -1
- data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +2 -0
- data/lib/packetgen/header/ospfv3/ls_request.rb +2 -0
- data/lib/packetgen/header/ospfv3/lsa.rb +9 -3
- data/lib/packetgen/header/ospfv3/lsa_header.rb +2 -1
- data/lib/packetgen/header/snmp.rb +3 -2
- data/lib/packetgen/header/tcp.rb +1 -20
- data/lib/packetgen/header/tcp/option.rb +8 -6
- data/lib/packetgen/inspect.rb +1 -17
- data/lib/packetgen/packet.rb +10 -6
- data/lib/packetgen/pcapng.rb +11 -11
- data/lib/packetgen/pcapng/block.rb +15 -2
- data/lib/packetgen/pcapng/epb.rb +22 -15
- data/lib/packetgen/pcapng/file.rb +166 -81
- data/lib/packetgen/pcapng/idb.rb +7 -9
- data/lib/packetgen/pcapng/shb.rb +35 -28
- data/lib/packetgen/pcapng/spb.rb +16 -12
- data/lib/packetgen/pcapng/unknown_block.rb +3 -11
- data/lib/packetgen/pcaprub_wrapper.rb +25 -11
- data/lib/packetgen/types.rb +1 -0
- data/lib/packetgen/types/abstract_tlv.rb +3 -1
- data/lib/packetgen/types/array.rb +17 -10
- data/lib/packetgen/types/cstring.rb +56 -19
- data/lib/packetgen/types/enum.rb +4 -0
- data/lib/packetgen/types/fieldable.rb +65 -0
- data/lib/packetgen/types/fields.rb +180 -113
- data/lib/packetgen/types/int.rb +15 -1
- data/lib/packetgen/types/int_string.rb +8 -0
- data/lib/packetgen/types/length_from.rb +18 -10
- data/lib/packetgen/types/oui.rb +2 -0
- data/lib/packetgen/types/string.rb +58 -7
- data/lib/packetgen/types/tlv.rb +2 -0
- data/lib/packetgen/unknown_packet.rb +84 -0
- data/lib/packetgen/utils.rb +6 -7
- data/lib/packetgen/version.rb +1 -1
- metadata +18 -15
data/lib/packetgen/pcapng/idb.rb
CHANGED
@@ -60,7 +60,7 @@ module PacketGen
|
|
60
60
|
# @option options [Integer] :block_len2 block total length
|
61
61
|
def initialize(options={})
|
62
62
|
super
|
63
|
-
|
63
|
+
endianness(options[:endian] || :little)
|
64
64
|
@packets = []
|
65
65
|
@options_decoded = false
|
66
66
|
recalc_block_len
|
@@ -74,15 +74,12 @@ module PacketGen
|
|
74
74
|
io = to_io(str_or_io)
|
75
75
|
return self if io.eof?
|
76
76
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
self[:reserved].read io.read(2)
|
81
|
-
self[:snaplen].read io.read(4)
|
77
|
+
%i[type block_len link_type reserved snaplen].each do |attr|
|
78
|
+
self[attr].read io.read(self[attr].sz)
|
79
|
+
end
|
82
80
|
self[:options].read io.read(self.block_len - MIN_SIZE)
|
83
|
-
|
81
|
+
read_blocklen2_and_check(io)
|
84
82
|
|
85
|
-
check_len_coherency
|
86
83
|
self
|
87
84
|
end
|
88
85
|
|
@@ -91,6 +88,7 @@ module PacketGen
|
|
91
88
|
# @return [self]
|
92
89
|
def <<(xpb)
|
93
90
|
@packets << xpb
|
91
|
+
xpb.interface = self
|
94
92
|
self
|
95
93
|
end
|
96
94
|
|
@@ -133,7 +131,7 @@ module PacketGen
|
|
133
131
|
|
134
132
|
while idx < options.length
|
135
133
|
opt_code, opt_len = options[idx, 4].unpack("#{packstr}2")
|
136
|
-
return options[idx + 4, 1].
|
134
|
+
return options[idx + 4, 1].unpack1('C') if opt_code == OPTION_IF_TSRESOL && opt_len == 1
|
137
135
|
|
138
136
|
idx += 4 + opt_len
|
139
137
|
end
|
data/lib/packetgen/pcapng/shb.rb
CHANGED
@@ -80,7 +80,7 @@ module PacketGen
|
|
80
80
|
super
|
81
81
|
@interfaces = []
|
82
82
|
@unknown_blocks = []
|
83
|
-
|
83
|
+
endianness(options[:endian] || :little)
|
84
84
|
recalc_block_len
|
85
85
|
self.type = options[:type] || PcapNG::SHB_TYPE.to_i
|
86
86
|
end
|
@@ -92,29 +92,15 @@ module PacketGen
|
|
92
92
|
io = to_io(str_or_io)
|
93
93
|
return self if io.eof?
|
94
94
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
case magic_str
|
100
|
-
when MAGIC_LITTLE
|
101
|
-
force_endianness :little if @endian == :big
|
102
|
-
when MAGIC_BIG
|
103
|
-
force_endianness :big if @endian == :little
|
104
|
-
else
|
105
|
-
raise InvalidFileError, 'Incorrect magic for Section Header Block'
|
95
|
+
self[:type].read check_shb(io)
|
96
|
+
%i[block_len magic ver_major ver_minor section_len].each do |attr|
|
97
|
+
self[attr].read io.read(self[attr].sz)
|
106
98
|
end
|
99
|
+
handle_magic_and_check(self[:magic].to_s)
|
107
100
|
|
108
|
-
|
109
|
-
|
110
|
-
self[:magic].read magic_str
|
111
|
-
self[:ver_major].read io.read(2)
|
112
|
-
self[:ver_minor].read io.read(2)
|
113
|
-
self[:section_len].read io.read(8)
|
114
|
-
self[:options].read io.read(self.block_len - MIN_SIZE)
|
115
|
-
self[:block_len2].read io.read(4)
|
101
|
+
read_options(io)
|
102
|
+
read_blocklen2_and_check(io)
|
116
103
|
|
117
|
-
check_len_coherency
|
118
104
|
self
|
119
105
|
end
|
120
106
|
|
@@ -123,6 +109,7 @@ module PacketGen
|
|
123
109
|
# @return [self]
|
124
110
|
def <<(idb)
|
125
111
|
@interfaces << idb
|
112
|
+
idb.section = self
|
126
113
|
self
|
127
114
|
end
|
128
115
|
|
@@ -137,17 +124,22 @@ module PacketGen
|
|
137
124
|
super + body
|
138
125
|
end
|
139
126
|
|
127
|
+
def add_unknown_block(block)
|
128
|
+
self.unknown_blocks << block
|
129
|
+
block.section = self
|
130
|
+
end
|
131
|
+
|
140
132
|
private
|
141
133
|
|
142
134
|
def force_endianness(endian)
|
143
135
|
@endian = endian
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
self[:
|
136
|
+
%i[type block_len magic block_len2].each do |attr|
|
137
|
+
self[attr] = Types::Int32.new(0, endian).read(self[attr].to_s)
|
138
|
+
end
|
139
|
+
%i[ver_major ver_minor].each do |attr|
|
140
|
+
self[attr] = Types::Int16.new(0, endian).read(self[attr].to_s)
|
141
|
+
end
|
142
|
+
self[:section_len] = Types::Int64.new(0, endian).read(self[:section_len].to_s)
|
151
143
|
end
|
152
144
|
|
153
145
|
# Check io contains a SHB
|
@@ -160,6 +152,21 @@ module PacketGen
|
|
160
152
|
type = type_str.unpack('H*').join
|
161
153
|
raise InvalidFileError, "Incorrect type (#{type})for Section Header Block"
|
162
154
|
end
|
155
|
+
|
156
|
+
def handle_magic_and_check(magic_str)
|
157
|
+
case magic_str
|
158
|
+
when MAGIC_LITTLE
|
159
|
+
force_endianness :little if endian == :big
|
160
|
+
when MAGIC_BIG
|
161
|
+
force_endianness :big if endian == :little
|
162
|
+
else
|
163
|
+
raise InvalidFileError, 'Incorrect magic for Section Header Block'
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def read_options(io)
|
168
|
+
self[:options].read io.read(self.block_len - MIN_SIZE)
|
169
|
+
end
|
163
170
|
end
|
164
171
|
end
|
165
172
|
end
|
data/lib/packetgen/pcapng/spb.rb
CHANGED
@@ -44,7 +44,7 @@ module PacketGen
|
|
44
44
|
# @option options [Integer] :block_len2 block total length
|
45
45
|
def initialize(options={})
|
46
46
|
super
|
47
|
-
|
47
|
+
endianness(options[:endian] || :little)
|
48
48
|
recalc_block_len
|
49
49
|
self.type = options[:type] || PcapNG::SPB_TYPE.to_i
|
50
50
|
end
|
@@ -66,19 +66,11 @@ module PacketGen
|
|
66
66
|
self[:type].read io.read(4)
|
67
67
|
self[:block_len].read io.read(4)
|
68
68
|
self[:orig_len].read io.read(4)
|
69
|
-
|
70
|
-
# CAUTION: snaplen == 0 -> no capture limit
|
71
|
-
data_len = if interface && interface.snaplen.to_i.positive?
|
72
|
-
[self[:orig_len].to_i, interface.snaplen.to_i].min
|
73
|
-
else
|
74
|
-
self[:orig_len].to_i
|
75
|
-
end
|
76
|
-
data_pad_len = (4 - (data_len % 4)) % 4
|
69
|
+
data_len = compute_data_len
|
77
70
|
self[:data].read io.read(data_len)
|
78
|
-
io
|
79
|
-
|
71
|
+
remove_padding(io, data_len)
|
72
|
+
read_blocklen2_and_check(io)
|
80
73
|
|
81
|
-
check_len_coherency
|
82
74
|
self.type ||= PcapNG::IDB_TYPE.to_i
|
83
75
|
self
|
84
76
|
end
|
@@ -90,6 +82,18 @@ module PacketGen
|
|
90
82
|
recalc_block_len
|
91
83
|
super
|
92
84
|
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
# Take care of IDB snaplen
|
89
|
+
# CAUTION: snaplen == 0 -> no capture limit
|
90
|
+
def compute_data_len
|
91
|
+
if interface && interface.snaplen.to_i.positive?
|
92
|
+
[self[:orig_len].to_i, interface.snaplen.to_i].min
|
93
|
+
else
|
94
|
+
self[:orig_len].to_i
|
95
|
+
end
|
96
|
+
end
|
93
97
|
end
|
94
98
|
end
|
95
99
|
end
|
@@ -29,7 +29,7 @@ module PacketGen
|
|
29
29
|
# @option options [Integer] :block_len2 block total length
|
30
30
|
def initialize(options={})
|
31
31
|
super
|
32
|
-
|
32
|
+
endianness(options[:endian] || :little)
|
33
33
|
recalc_block_len
|
34
34
|
end
|
35
35
|
|
@@ -44,21 +44,13 @@ module PacketGen
|
|
44
44
|
# @param [::String,IO] str_or_io
|
45
45
|
# @return [self]
|
46
46
|
def read(str_or_io)
|
47
|
-
io =
|
48
|
-
str_or_io
|
49
|
-
else
|
50
|
-
StringIO.new(force_binary(str_or_io.to_s))
|
51
|
-
end
|
47
|
+
io = to_io(str_or_io)
|
52
48
|
return self if io.eof?
|
53
49
|
|
54
50
|
self[:type].read io.read(4)
|
55
51
|
self[:block_len].read io.read(4)
|
56
52
|
self[:body].read io.read(self[:block_len].to_i - MIN_SIZE)
|
57
|
-
|
58
|
-
|
59
|
-
unless self[:block_len].to_i == self[:block_len2].to_i
|
60
|
-
raise InvalidFileError, 'Incoherency in Header Block'
|
61
|
-
end
|
53
|
+
read_blocklen2_and_check(io)
|
62
54
|
|
63
55
|
self
|
64
56
|
end
|
@@ -23,26 +23,42 @@ module PacketGen
|
|
23
23
|
# @param [String] iface interface name
|
24
24
|
# @param [Integer] snaplen
|
25
25
|
# @param [Boolean] promisc
|
26
|
+
# @param [Boolean] monitor
|
26
27
|
# @return [PCAPRUB::Pcap]
|
27
|
-
|
28
|
-
|
28
|
+
# @author Sylvain Daubert
|
29
|
+
# @author optix2000 - add support for setting monitor mode
|
30
|
+
# @since 3.1.5 add monitor argument
|
31
|
+
def self.open_iface(iface:, snaplen: DEFAULT_SNAPLEN, promisc: DEFAULT_PROMISC, monitor: nil)
|
32
|
+
pcap = PCAPRUB::Pcap.create(iface)
|
33
|
+
pcap.setsnaplen(snaplen)
|
34
|
+
pcap.setpromisc(promisc)
|
35
|
+
pcap.settimeout(TIMEOUT)
|
36
|
+
# Monitor MUST be set before pcap is activated
|
37
|
+
pcap.setmonitor monitor unless monitor.nil?
|
38
|
+
pcap.activate
|
29
39
|
end
|
30
40
|
|
41
|
+
# rubocop:disable Metrics/ParameterLists
|
42
|
+
|
31
43
|
# Capture packets from a network interface
|
32
44
|
# @param [String] iface interface name
|
33
45
|
# @param [Integer] snaplen
|
34
46
|
# @param [Boolean] promisc
|
35
47
|
# @param [String] filter BPF filter
|
48
|
+
# @param [Boolean] monitor
|
36
49
|
# @yieldparam [String] packet_data binary packet data
|
37
50
|
# @return [void]
|
38
|
-
|
39
|
-
|
51
|
+
# @author Sylvain Daubert
|
52
|
+
# @author optix2000 - add support for setting monitor mode
|
53
|
+
# @since 3.1.5 add monitor argument
|
54
|
+
def self.capture(iface:, snaplen: DEFAULT_SNAPLEN, promisc: DEFAULT_PROMISC, filter: nil, monitor: nil, &block)
|
55
|
+
pcap = self.open_iface(iface: iface, snaplen: snaplen, promisc: promisc, monitor: monitor)
|
40
56
|
pcap.setfilter filter unless filter.nil?
|
41
|
-
pcap.each
|
42
|
-
yield packet_data
|
43
|
-
end
|
57
|
+
pcap.each(&block)
|
44
58
|
end
|
45
59
|
|
60
|
+
# rubocop:enable Metrics/ParameterLists
|
61
|
+
|
46
62
|
# Inject given data onto wire
|
47
63
|
# @param [String] iface interface name
|
48
64
|
# @param [String] data to inject
|
@@ -58,10 +74,8 @@ module PacketGen
|
|
58
74
|
# @yieldparam [String] data binary packet data
|
59
75
|
# @return [void]
|
60
76
|
# @author Kent Gruber
|
61
|
-
def self.read_pcap(filename
|
62
|
-
PCAPRUB::Pcap.open_offline(filename).each_packet
|
63
|
-
yield packet
|
64
|
-
end
|
77
|
+
def self.read_pcap(filename:, &block)
|
78
|
+
PCAPRUB::Pcap.open_offline(filename).each_packet(&block)
|
65
79
|
end
|
66
80
|
end
|
67
81
|
end
|
data/lib/packetgen/types.rb
CHANGED
@@ -58,6 +58,8 @@ module PacketGen
|
|
58
58
|
# @since 3.1.0
|
59
59
|
# @since 3.1.1 add +:aliases+ keyword to {#initialize}
|
60
60
|
class AbstractTLV < Types::Fields
|
61
|
+
include Fieldable
|
62
|
+
|
61
63
|
class <<self
|
62
64
|
# @return [Hash]
|
63
65
|
attr_accessor :aliases
|
@@ -169,7 +171,7 @@ module PacketGen
|
|
169
171
|
# @return [String]
|
170
172
|
def to_human
|
171
173
|
my_value = self[:value].is_a?(String) ? self[:value].inspect : self[:value].to_human
|
172
|
-
|
174
|
+
'type:%s,length:%u,value:%s' % [human_type, length, my_value]
|
173
175
|
end
|
174
176
|
|
175
177
|
private
|
@@ -27,6 +27,9 @@ module PacketGen
|
|
27
27
|
# @author Sylvain Daubert
|
28
28
|
class Array
|
29
29
|
extend Forwardable
|
30
|
+
include Enumerable
|
31
|
+
include Fieldable
|
32
|
+
include LengthFrom
|
30
33
|
|
31
34
|
# @!method [](index)
|
32
35
|
# Return the element at +index+.
|
@@ -54,9 +57,6 @@ module PacketGen
|
|
54
57
|
def_delegators :@array, :[], :clear, :each, :empty?, :first, :last, :size
|
55
58
|
alias length size
|
56
59
|
|
57
|
-
include Enumerable
|
58
|
-
include LengthFrom
|
59
|
-
|
60
60
|
# Separator used in {#to_human}.
|
61
61
|
# May be ovverriden by subclasses
|
62
62
|
HUMAN_SEPARATOR = ','
|
@@ -163,11 +163,8 @@ module PacketGen
|
|
163
163
|
return self if @counter&.to_i&.zero?
|
164
164
|
|
165
165
|
str = read_with_length_from(str)
|
166
|
-
klass = self.class.set_of_klass
|
167
166
|
until str.empty?
|
168
|
-
obj =
|
169
|
-
real_klass = real_type(obj)
|
170
|
-
obj = real_klass.new.read(str) unless real_klass == klass
|
167
|
+
obj = create_object_from_str(str)
|
171
168
|
@array << obj
|
172
169
|
str.slice!(0, obj.sz)
|
173
170
|
break if @counter && self.size == @counter.to_i
|
@@ -203,9 +200,7 @@ module PacketGen
|
|
203
200
|
|
204
201
|
def record_from_hash(hsh)
|
205
202
|
obj_klass = self.class.set_of_klass
|
206
|
-
unless obj_klass
|
207
|
-
raise NotImplementedError, 'class should define #record_from_hash or declare type of elements in set with .set_of'
|
208
|
-
end
|
203
|
+
raise NotImplementedError, 'class should define #record_from_hash or declare type of elements in set with .set_of' unless obj_klass
|
209
204
|
|
210
205
|
obj = obj_klass.new(hsh) if obj_klass
|
211
206
|
klass = real_type(obj)
|
@@ -215,6 +210,18 @@ module PacketGen
|
|
215
210
|
def real_type(obj)
|
216
211
|
obj.class
|
217
212
|
end
|
213
|
+
|
214
|
+
def create_object_from_str(str)
|
215
|
+
klass = self.class.set_of_klass
|
216
|
+
obj = klass.new.read(str)
|
217
|
+
real_klass = real_type(obj)
|
218
|
+
|
219
|
+
if real_klass == klass
|
220
|
+
obj
|
221
|
+
else
|
222
|
+
real_klass.new.read(str)
|
223
|
+
end
|
224
|
+
end
|
218
225
|
end
|
219
226
|
|
220
227
|
# Specialized array to handle serie of {Int8}.
|
@@ -6,15 +6,30 @@
|
|
6
6
|
# Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
|
7
7
|
# This program is published under MIT license.
|
8
8
|
|
9
|
+
require 'forwardable'
|
10
|
+
|
9
11
|
module PacketGen
|
10
12
|
module Types
|
11
13
|
# This class handles null-terminated strings (aka C strings).
|
12
14
|
# @author Sylvain Daubert
|
13
|
-
|
15
|
+
# @since 3.1.6 no more a subclass or regular String
|
16
|
+
class CString
|
17
|
+
extend Forwardable
|
18
|
+
include Fieldable
|
19
|
+
|
20
|
+
def_delegators :@string, :[], :length, :size, :inspect, :==,
|
21
|
+
:unpack, :force_encoding, :encoding, :index, :empty?,
|
22
|
+
:encode, :slice, :slice!
|
23
|
+
|
24
|
+
# @return [::String]
|
25
|
+
attr_reader :string
|
26
|
+
# @return [Integer]
|
27
|
+
attr_reader :static_length
|
28
|
+
|
14
29
|
# @param [Hash] options
|
15
30
|
# @option options [Integer] :static_length set a static length for this string
|
16
31
|
def initialize(options={})
|
17
|
-
|
32
|
+
register_internal_string(+'')
|
18
33
|
@static_length = options[:static_length]
|
19
34
|
end
|
20
35
|
|
@@ -22,38 +37,49 @@ module PacketGen
|
|
22
37
|
# @return [String] self
|
23
38
|
def read(str)
|
24
39
|
s = str.to_s
|
25
|
-
s = s[0,
|
26
|
-
|
27
|
-
|
28
|
-
self.replace s
|
40
|
+
s = s[0, static_length] if static_length?
|
41
|
+
register_internal_string s
|
42
|
+
remove_null_character
|
29
43
|
self
|
30
44
|
end
|
31
45
|
|
32
46
|
# get null-terminated string
|
33
47
|
# @return [String]
|
34
48
|
def to_s
|
35
|
-
if
|
36
|
-
|
37
|
-
|
38
|
-
s[-1] = "\x00".encode(s.encoding)
|
39
|
-
PacketGen.force_binary s
|
40
|
-
else
|
41
|
-
PacketGen.force_binary(self + "\0" * (@static_length - self.length))
|
42
|
-
end
|
49
|
+
if static_length?
|
50
|
+
s = string[0, static_length - 1]
|
51
|
+
s << "\x00" * (static_length - s.length)
|
43
52
|
else
|
44
|
-
|
53
|
+
s = "#{string}\x00"
|
45
54
|
end
|
55
|
+
PacketGen.force_binary(s)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Append the given string to CString
|
59
|
+
# @param [#to_s] str
|
60
|
+
# @return [self]
|
61
|
+
def <<(str)
|
62
|
+
@string << str.to_s
|
63
|
+
remove_null_character
|
64
|
+
self
|
46
65
|
end
|
47
66
|
|
48
67
|
# @return [Integer]
|
49
68
|
def sz
|
50
|
-
if
|
51
|
-
|
69
|
+
if static_length?
|
70
|
+
static_length
|
52
71
|
else
|
53
72
|
to_s.size
|
54
73
|
end
|
55
74
|
end
|
56
75
|
|
76
|
+
# Say if a static length is defined
|
77
|
+
# @return [Boolean]
|
78
|
+
# @since 3.1.6
|
79
|
+
def static_length?
|
80
|
+
!static_length.nil?
|
81
|
+
end
|
82
|
+
|
57
83
|
# Populate CString from a human readable string
|
58
84
|
# @param [String] str
|
59
85
|
# @return [self]
|
@@ -63,8 +89,19 @@ module PacketGen
|
|
63
89
|
|
64
90
|
# @return [String]
|
65
91
|
def to_human
|
66
|
-
|
67
|
-
|
92
|
+
string
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
def register_internal_string(str)
|
98
|
+
@string = str
|
99
|
+
PacketGen.force_binary(@string)
|
100
|
+
end
|
101
|
+
|
102
|
+
def remove_null_character
|
103
|
+
idx = string.index(0.chr)
|
104
|
+
register_internal_string(string[0, idx]) unless idx.nil?
|
68
105
|
end
|
69
106
|
end
|
70
107
|
end
|