packetgen 2.1.3 → 2.1.4
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/lib/packetgen/header.rb +1 -0
- data/lib/packetgen/header/asn1_base.rb +20 -1
- data/lib/packetgen/header/base.rb +27 -3
- data/lib/packetgen/header/dot11.rb +24 -6
- data/lib/packetgen/header/dot1x.rb +19 -0
- data/lib/packetgen/header/eap.rb +238 -0
- data/lib/packetgen/header/eap/fast.rb +27 -0
- data/lib/packetgen/header/eap/md5.rb +34 -0
- data/lib/packetgen/header/eap/tls.rb +73 -0
- data/lib/packetgen/header/eap/ttls.rb +78 -0
- data/lib/packetgen/header/eth.rb +1 -0
- data/lib/packetgen/header/ike/auth.rb +17 -53
- data/lib/packetgen/header/ike/id.rb +14 -51
- data/lib/packetgen/header/ike/ts.rb +3 -25
- data/lib/packetgen/header/ip.rb +1 -0
- data/lib/packetgen/header/ipv6.rb +1 -0
- data/lib/packetgen/inspect.rb +4 -2
- data/lib/packetgen/packet.rb +16 -4
- data/lib/packetgen/pcapng/file.rb +0 -3
- data/lib/packetgen/types/fields.rb +14 -13
- data/lib/packetgen/types/int.rb +61 -0
- data/lib/packetgen/version.rb +1 -1
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 36c2e8a9384d7c08723de6f529893d0dd42e5d8d
|
4
|
+
data.tar.gz: 0e91b3917d405a1a09b75a7863685645b52827d9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 55414180e5ca3bcc69cee0a00a84cbe79635a2809d3f999d35a9d6fab725b5dfc153ea5cc087c10d08985caf10c60aa7ee23df2fb4537d7ca3d6924789f2e614
|
7
|
+
data.tar.gz: 51ea04c7c3a1544911ca26f4c6b8c066bc58aa0255a2dd6241f21b668fee9e16c7def036d62722c7e826f77947128225c1a56d5ee4ef27aa71d0eaff55352b5e
|
data/lib/packetgen/header.rb
CHANGED
@@ -93,6 +93,7 @@ require_relative 'header/icmpv6'
|
|
93
93
|
require_relative 'header/gre'
|
94
94
|
require_relative 'header/udp'
|
95
95
|
require_relative 'header/tcp'
|
96
|
+
require_relative 'header/eap'
|
96
97
|
require_relative 'header/esp'
|
97
98
|
require_relative 'header/ike'
|
98
99
|
require_relative 'header/dns'
|
@@ -15,8 +15,8 @@ module PacketGen
|
|
15
15
|
# @author Sylvain Daubert
|
16
16
|
class ASN1Base < RASN1::Model
|
17
17
|
|
18
|
-
# @api private
|
19
18
|
# Reference on packet which owns this header
|
19
|
+
# @return [Packet,nil]
|
20
20
|
attr_accessor :packet
|
21
21
|
|
22
22
|
# Give protocol name for this class
|
@@ -65,6 +65,25 @@ module PacketGen
|
|
65
65
|
true
|
66
66
|
end
|
67
67
|
|
68
|
+
# @api private
|
69
|
+
# @since 2.1.4
|
70
|
+
# Set packet to which this header belongs
|
71
|
+
# @param [Packet] packet
|
72
|
+
# @return [Packet] packet
|
73
|
+
def packet=(packet)
|
74
|
+
@packet = packet
|
75
|
+
added_to_packet(packet)
|
76
|
+
@packet
|
77
|
+
end
|
78
|
+
|
79
|
+
# @abstract This method is called when a header is added to a packet.
|
80
|
+
# This base method does nothing but may be overriden by subclasses.
|
81
|
+
# @param [Packet] packet packet to which self is added
|
82
|
+
# @return [void]
|
83
|
+
# @since 2.1.4
|
84
|
+
def added_to_packet(packet)
|
85
|
+
end
|
86
|
+
|
68
87
|
alias :parse :parse!
|
69
88
|
alias :to_s :to_der
|
70
89
|
|
@@ -35,7 +35,12 @@ module PacketGen
|
|
35
35
|
when Proc
|
36
36
|
fields.send "#{self[:key]}=", self[:value].call(nil)
|
37
37
|
else
|
38
|
-
|
38
|
+
attr = if self[:key].to_s.end_with?('?')
|
39
|
+
self[:key].to_s[0..-2]
|
40
|
+
else
|
41
|
+
self[:key]
|
42
|
+
end
|
43
|
+
fields.send "#{attr}=", self[:value]
|
39
44
|
end
|
40
45
|
end
|
41
46
|
end
|
@@ -127,9 +132,9 @@ module PacketGen
|
|
127
132
|
end
|
128
133
|
end
|
129
134
|
|
130
|
-
# @api private
|
131
135
|
# Reference on packet which owns this header
|
132
|
-
|
136
|
+
# @return [Packet,nil]
|
137
|
+
attr_reader :packet
|
133
138
|
|
134
139
|
# On inheritage, create +@known_headers+ class variable
|
135
140
|
# @param [Class] klass
|
@@ -217,6 +222,25 @@ module PacketGen
|
|
217
222
|
true
|
218
223
|
end
|
219
224
|
|
225
|
+
# @api private
|
226
|
+
# Set packet to which this header belongs
|
227
|
+
# @param [Packet] packet
|
228
|
+
# @return [Packet] packet
|
229
|
+
# @since 2.1.4
|
230
|
+
def packet=(packet)
|
231
|
+
@packet = packet
|
232
|
+
added_to_packet(packet)
|
233
|
+
@packet
|
234
|
+
end
|
235
|
+
|
236
|
+
# @abstract This method is called when a header is added to a packet.
|
237
|
+
# This base method does nothing but may be overriden by subclasses.
|
238
|
+
# @param [Packet] packet packet to which self is added
|
239
|
+
# @return [void]
|
240
|
+
# @since 2.1.4
|
241
|
+
def added_to_packet(packet)
|
242
|
+
end
|
243
|
+
|
220
244
|
# @api private
|
221
245
|
# Get +header+ id in packet headers array
|
222
246
|
# @param [Header] header
|
@@ -67,6 +67,7 @@ module PacketGen
|
|
67
67
|
pcap = PCAPRUB::Pcap.open_live(iface, PCAP_SNAPLEN, PCAP_PROMISC,
|
68
68
|
PCAP_TIMEOUT)
|
69
69
|
pcap.inject self.to_s
|
70
|
+
pcap.close
|
70
71
|
end
|
71
72
|
end
|
72
73
|
self.add_class PPI
|
@@ -127,6 +128,7 @@ module PacketGen
|
|
127
128
|
pcap = PCAPRUB::Pcap.open_live(iface, PCAP_SNAPLEN, PCAP_PROMISC,
|
128
129
|
PCAP_TIMEOUT)
|
129
130
|
pcap.inject self.to_s
|
131
|
+
pcap.close
|
130
132
|
end
|
131
133
|
end
|
132
134
|
self.add_class RadioTap
|
@@ -161,11 +163,15 @@ module PacketGen
|
|
161
163
|
# Control frames may be created this way:
|
162
164
|
# pkt = PacketGen.gen('Dot11::Control', subtype: 13) # Ack control frame
|
163
165
|
# pkt.dot11_control # => PacketGen::Header::Dot11::Control
|
166
|
+
# # #dot11 is a shortcut for #dot11_control
|
167
|
+
# pkt.dot11 # => PacketGen::Header::Dot11::Control
|
164
168
|
#
|
165
169
|
# === IEEE802.11 management frames
|
166
170
|
# Management frames may be created this way:
|
167
171
|
# pkt = PacketGen.gen('Dot11::Management')
|
168
172
|
# pkt.dot11_management # => PacketGen::Header::Dot11::Management
|
173
|
+
# # #dot11 is a shortcut for #dot11_management
|
174
|
+
# pkt.dot11 # => PacketGen::Header::Dot11::Management
|
169
175
|
# Management frames are usually specialized, AssociationRequest by example:
|
170
176
|
# pkt.add('Dot11::AssoReq')
|
171
177
|
# pkt.dot11_assoreq # => PacketGen::Header::Dot11::AssoReq
|
@@ -177,13 +183,14 @@ module PacketGen
|
|
177
183
|
# Data frames may be created this way:
|
178
184
|
# pkt = PacketGen.gen('Dot11::Data')
|
179
185
|
# pkt.dot11_data # => PacketGen::Header::Dot11::Data
|
186
|
+
# # #dot11 is a shortcut for #dot11_data
|
187
|
+
# pkt.dot11 # => PacketGen::Header::Dot11::Data
|
180
188
|
#
|
181
189
|
# == Parse Dot11 packets
|
182
190
|
# When parsing a Dot11 packet, Dot11 subclass is created from +type+ value.
|
183
|
-
# Dot11 header should then be accessed through +Packet#
|
184
|
-
#
|
185
|
-
#
|
186
|
-
# A +Packet#dot11+ may exist for unknown types.
|
191
|
+
# Dot11 header should then be accessed through +Packet#dot11+, whatever
|
192
|
+
# the frame type is. But, specialized methods also exist: by example,
|
193
|
+
# for a control frame, +Packet#dot11_control+ may also be used.
|
187
194
|
#
|
188
195
|
# == Send Dot11 packets
|
189
196
|
# To send a Dot11 packet, a RadioTap header is needed:
|
@@ -366,8 +373,19 @@ module PacketGen
|
|
366
373
|
def to_w(iface)
|
367
374
|
pcap = PCAPRUB::Pcap.open_live(iface, PCAP_SNAPLEN, PCAP_PROMISC,
|
368
375
|
PCAP_TIMEOUT)
|
369
|
-
|
370
|
-
pcap.
|
376
|
+
pcap.inject self.to_s
|
377
|
+
pcap.close
|
378
|
+
end
|
379
|
+
|
380
|
+
# Callback called when a Dot11 header is added to a packet
|
381
|
+
# Here, add +#dot11+ method as a shortcut to existing
|
382
|
+
# +#dot11_(control|management|data)+.
|
383
|
+
# @param [Packet] packet
|
384
|
+
# @return [void]
|
385
|
+
def added_to_packet(packet)
|
386
|
+
unless packet.respond_to? :dot11
|
387
|
+
packet.instance_eval("def dot11(arg=nil); header(#{self.class}, arg); end")
|
388
|
+
end
|
371
389
|
end
|
372
390
|
|
373
391
|
private
|
@@ -46,11 +46,30 @@ module PacketGen
|
|
46
46
|
# @return [Types::String,Header::Base]
|
47
47
|
define_field :body, Types::String
|
48
48
|
|
49
|
+
# Populate object from string
|
50
|
+
# @param [String] str
|
51
|
+
# @return [self]
|
52
|
+
def read(str)
|
53
|
+
return self if str.nil?
|
54
|
+
self[:version].read(str[0, 1])
|
55
|
+
self[:type].read(str[1, 1])
|
56
|
+
self[:length].read(str[2, 2])
|
57
|
+
self[:body].read(str[4, self.length])
|
58
|
+
self
|
59
|
+
end
|
60
|
+
|
49
61
|
# Get human readable type
|
50
62
|
# @return [String]
|
51
63
|
def human_type
|
52
64
|
self[:type].to_human
|
53
65
|
end
|
66
|
+
|
67
|
+
# Calculate and set body length
|
68
|
+
# @return [Integer]
|
69
|
+
# @since 2.1.4
|
70
|
+
def calc_length
|
71
|
+
self.length = body.sz
|
72
|
+
end
|
54
73
|
end
|
55
74
|
|
56
75
|
Eth.bind_header Dot1x, ethertype: Dot1x::ETHERTYPE
|
@@ -0,0 +1,238 @@
|
|
1
|
+
# This file is part of PacketGen
|
2
|
+
# See https://github.com/sdaubert/packetgen for more informations
|
3
|
+
# Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
|
4
|
+
# This program is published under MIT license.
|
5
|
+
|
6
|
+
module PacketGen
|
7
|
+
module Header
|
8
|
+
|
9
|
+
# Extensible Authentication Protocol (EAP),
|
10
|
+
# {https://tools.ietf.org/html/rfc3748 RFC 3748}
|
11
|
+
#
|
12
|
+
# A EAP header has:
|
13
|
+
# * a {#code} field ({Types::Int8Enum}),
|
14
|
+
# * a {#id} field ({Types::Int8}),
|
15
|
+
# * a {#length} field ({Types::Int16}).
|
16
|
+
# Request (code 1) and Response (code 2) packets also have:
|
17
|
+
# * a {#type} field (+Types::Int8Enum+).
|
18
|
+
# And Expanded Types (type 254) packets also have:
|
19
|
+
# * a {#vendor_id} field ({Types::Int24}),
|
20
|
+
# * a {#vendor_type} field ({Types::Int32}).
|
21
|
+
# Finally, all packets have a {#body} ({Types::String}).
|
22
|
+
#
|
23
|
+
# == Create EAP headers
|
24
|
+
# An EAP header may be created this way:
|
25
|
+
# # create a request header with default type (1)
|
26
|
+
# eap = EAP.new(code: 1) # => PacketGen::Header::EAP
|
27
|
+
# # the same
|
28
|
+
# eap = EAP.new(code: 'Request') # => PacketGen::Header::EAP
|
29
|
+
# # create a Response header of type Nak
|
30
|
+
# nak = EAP.new(code: 'Response', type: 'Nak')
|
31
|
+
#
|
32
|
+
# === Specialized headers
|
33
|
+
# Some EAP has a specialized class:
|
34
|
+
# * EAP-MD5,
|
35
|
+
# * EAP-TLS,
|
36
|
+
# * EAP-TTLS,
|
37
|
+
# * EAP-FAST.
|
38
|
+
# Creating such a header is fairly simple:
|
39
|
+
# # Generate a EAP-TLS Response (type is forced to 13)
|
40
|
+
# eap = EAP::TLS.new(code: 2) # => PacketGen::Header::EAP::TLS
|
41
|
+
#
|
42
|
+
# == Header accessors
|
43
|
+
# EAP headers may be accessed through +Packet#eap+ accessor.
|
44
|
+
# As EAP has specialized subclasses ({EAP::MD5}, {EAP::TLS}, {EAP::TTLS} and
|
45
|
+
# {EAP::FAST}), these headers may be accessed through +#eap_md5+, +#eap_tls+,
|
46
|
+
# +#eap_ttls+ and +#eap_fast+, respectively. But +#eap+ is still here as a
|
47
|
+
# shortcut.
|
48
|
+
#
|
49
|
+
# == Parse EAP packets
|
50
|
+
# When parsing an EAP packet, EAP subclass may be created from +type+ value.
|
51
|
+
#
|
52
|
+
# So result of parsing a EAP header may be a {EAP}, {EAP::MD5}, {EAP::TLS},
|
53
|
+
# {EAP::TTLS} or {EAP::FAST} instance. But this instance is still accessible
|
54
|
+
# through +Packet#eap+.
|
55
|
+
# @author Sylvain Daubert
|
56
|
+
# @since 2.1.4
|
57
|
+
class EAP < Base
|
58
|
+
|
59
|
+
# EAP known codes
|
60
|
+
CODES = {
|
61
|
+
'Request' => 1,
|
62
|
+
'Response' => 2,
|
63
|
+
'Success' => 3,
|
64
|
+
'Failure' => 4
|
65
|
+
}
|
66
|
+
|
67
|
+
# EAP known request/response types
|
68
|
+
TYPES = {
|
69
|
+
'Identity' => 1,
|
70
|
+
'Notification' => 2,
|
71
|
+
'Nak' => 3,
|
72
|
+
'MD5-Challenge' => 4,
|
73
|
+
'One Time Password' => 5,
|
74
|
+
'Generic Token Card' => 6,
|
75
|
+
'EAP-TLS' => 13,
|
76
|
+
'EAP-TTLS' => 21,
|
77
|
+
'EAP-FAST' => 43,
|
78
|
+
'Expanded Types' => 254,
|
79
|
+
'Experimental Use' => 255
|
80
|
+
}
|
81
|
+
|
82
|
+
# @!attribute code
|
83
|
+
# @return [Integer] 8-bit EAP code
|
84
|
+
define_field :code, Types::Int8Enum, enum: CODES
|
85
|
+
|
86
|
+
# @!attribute id
|
87
|
+
# @return [Integer] 8-bit identifier
|
88
|
+
define_field :id, Types::Int8
|
89
|
+
|
90
|
+
# @!attribute length
|
91
|
+
# @return [Integer] 16-bit length of EAP packet
|
92
|
+
define_field :length, Types::Int16, default: 4
|
93
|
+
|
94
|
+
# @!attribute type
|
95
|
+
# This field is present only for Request or Response packets,
|
96
|
+
# with type different from Expanded Types (254).
|
97
|
+
# @return [Integer] 8-bit request or response type
|
98
|
+
define_field :type, Types::Int8Enum, enum: TYPES,
|
99
|
+
optional: ->(eap) { eap.has_type? }
|
100
|
+
|
101
|
+
# @!attribute vendor_id
|
102
|
+
# This field is present only for Request or Response packets,
|
103
|
+
# with type equal to +Expanded Types+ (254).
|
104
|
+
# @return [Integer] 24-bit vendor ID
|
105
|
+
define_field :vendor_id, Types::Int24,
|
106
|
+
optional: ->(eap) { eap.has_type? and eap.type == 254 }
|
107
|
+
|
108
|
+
# @!attribute vendor_type
|
109
|
+
# This field is present only for Request or Response packets,
|
110
|
+
# with type equal to +Expanded Types+ (254).
|
111
|
+
# @return [Integer] 32-bit vendor type
|
112
|
+
define_field :vendor_type, Types::Int32,
|
113
|
+
optional: ->(eap) { eap.has_type? and eap.type == 254 }
|
114
|
+
|
115
|
+
# @!attribute body
|
116
|
+
# @return [Types::String, Header::Base]
|
117
|
+
define_field :body, Types::String
|
118
|
+
|
119
|
+
# @return [EAP]
|
120
|
+
def initialize(options={})
|
121
|
+
super
|
122
|
+
calc_length if options[:length].nil?
|
123
|
+
end
|
124
|
+
|
125
|
+
# @private
|
126
|
+
alias old_read read
|
127
|
+
|
128
|
+
# Populate object from a binary string
|
129
|
+
# @param [String] str
|
130
|
+
# @return [Dot11] may return a subclass object if a more specific class
|
131
|
+
# may be determined
|
132
|
+
def read(str)
|
133
|
+
if self.class == EAP
|
134
|
+
super str
|
135
|
+
|
136
|
+
if has_type?
|
137
|
+
obj = case self.type
|
138
|
+
when 4
|
139
|
+
EAP::MD5.new.read(str)
|
140
|
+
when 13
|
141
|
+
EAP::TLS.new.read(str)
|
142
|
+
when 21
|
143
|
+
EAP::TTLS.new.read(str)
|
144
|
+
when 43
|
145
|
+
EAP::FAST.new.read(str)
|
146
|
+
else
|
147
|
+
self
|
148
|
+
end
|
149
|
+
return obj
|
150
|
+
else
|
151
|
+
return self
|
152
|
+
end
|
153
|
+
else
|
154
|
+
super str
|
155
|
+
end
|
156
|
+
self
|
157
|
+
end
|
158
|
+
|
159
|
+
# Get human readable code
|
160
|
+
# @return [String]
|
161
|
+
def human_code
|
162
|
+
self[:code].to_human
|
163
|
+
end
|
164
|
+
|
165
|
+
# Get human readable type
|
166
|
+
# @return [String]
|
167
|
+
# @raise [ParseError] not a Request nor a Response packet
|
168
|
+
def human_type
|
169
|
+
raise ParseError, 'not a Request nor a Response' unless has_type?
|
170
|
+
self[:type].to_human
|
171
|
+
end
|
172
|
+
|
173
|
+
# Is packet a request?
|
174
|
+
# @return [Boolean]
|
175
|
+
def request?
|
176
|
+
code == CODES['Request']
|
177
|
+
end
|
178
|
+
|
179
|
+
# Is packet a response?
|
180
|
+
# @return [Boolean]
|
181
|
+
def response?
|
182
|
+
code == CODES['Response']
|
183
|
+
end
|
184
|
+
|
185
|
+
# Is packet a success?
|
186
|
+
# @return [Boolean]
|
187
|
+
def success?
|
188
|
+
code == CODES['Success']
|
189
|
+
end
|
190
|
+
|
191
|
+
# Is packet a failure?
|
192
|
+
# @return [Boolean]
|
193
|
+
def failure?
|
194
|
+
code == CODES['Failure']
|
195
|
+
end
|
196
|
+
|
197
|
+
# Return an array of desired authentication types from a Nak packet
|
198
|
+
# @return [Array<Integer>]
|
199
|
+
# @raise [ParseError] not a Nak packet
|
200
|
+
def desired_auth_type
|
201
|
+
if code != 2 and type != 3
|
202
|
+
raise ParseError, 'not a Nak response'
|
203
|
+
end
|
204
|
+
body.to_s.unpack('C*')
|
205
|
+
end
|
206
|
+
|
207
|
+
# Calculate length field from content
|
208
|
+
# @return [Integer]
|
209
|
+
def calc_length
|
210
|
+
self.length = sz
|
211
|
+
end
|
212
|
+
|
213
|
+
# Say is this EAP header has {#type} field
|
214
|
+
# @return [Boolean]
|
215
|
+
def has_type?
|
216
|
+
[1,2].include?(self.code)
|
217
|
+
end
|
218
|
+
|
219
|
+
# Callback called when a EAP header is added to a packet
|
220
|
+
# Here, add +#eap+ method as a shortcut to existing
|
221
|
+
# +#eap_(md5|tls|ttls|fast)+.
|
222
|
+
# @param [Packet] packet
|
223
|
+
# @return [void]
|
224
|
+
def added_to_packet(packet)
|
225
|
+
unless packet.respond_to? :eap
|
226
|
+
packet.instance_eval("def eap(arg=nil); header(#{self.class}, arg); end")
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
Dot1x.bind_header EAP, type: 0
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
require_relative 'eap/md5'
|
236
|
+
require_relative 'eap/tls'
|
237
|
+
require_relative 'eap/ttls'
|
238
|
+
require_relative 'eap/fast'
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# This file is part of PacketGen
|
2
|
+
# See https://github.com/sdaubert/packetgen for more informations
|
3
|
+
# Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
|
4
|
+
# This program is published under MIT license.
|
5
|
+
|
6
|
+
module PacketGen
|
7
|
+
module Header
|
8
|
+
class EAP
|
9
|
+
|
10
|
+
# Extensible Authentication Protocol (EAP) - Flexible Authentication variable
|
11
|
+
# Secure Tunneling, {https://tools.ietf.org/html/rfc4851 RFC 4851}
|
12
|
+
#
|
13
|
+
# {EAP::FAST} has following fields:
|
14
|
+
# * {#flags} ({Types::Int8}),
|
15
|
+
# * optionally {#message_length} ({Types::Int32}), if +#l?+ is +true+,
|
16
|
+
# * {#body} ({Types::String}).
|
17
|
+
# @author Sylvain Daubert
|
18
|
+
# @since 2.1.4
|
19
|
+
class FAST < TTLS
|
20
|
+
# @return [EAP::FAST]
|
21
|
+
def initialize(options={})
|
22
|
+
super({ type: 43 }.merge!(options))
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# This file is part of PacketGen
|
2
|
+
# See https://github.com/sdaubert/packetgen for more informations
|
3
|
+
# Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
|
4
|
+
# This program is published under MIT license.
|
5
|
+
|
6
|
+
module PacketGen
|
7
|
+
module Header
|
8
|
+
class EAP
|
9
|
+
|
10
|
+
# Extensible Authentication Protocol (EAP) -
|
11
|
+
# {https://tools.ietf.org/html/rfc3748#section-5.4 MD5 challenge}
|
12
|
+
# @author Sylvain Daubert
|
13
|
+
# @since 2.1.4
|
14
|
+
class MD5 < EAP
|
15
|
+
delete_field :body
|
16
|
+
# @!attribute value_size
|
17
|
+
# @return [Integer] 8-bit value size
|
18
|
+
define_field :value_size, Types::Int8
|
19
|
+
# @!attribute value
|
20
|
+
# @return [::String]
|
21
|
+
define_field :value, Types::String,
|
22
|
+
builder: ->(h) { Types::String.new('', length_from: h[:value_size]) }
|
23
|
+
# @!attribute optional_name
|
24
|
+
# @return [::String]
|
25
|
+
define_field :optional_name, Types::String
|
26
|
+
|
27
|
+
# @return [EAP::MD5]
|
28
|
+
def initialize(options={})
|
29
|
+
super({ type: 4 }.merge!(options))
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# This file is part of PacketGen
|
2
|
+
# See https://github.com/sdaubert/packetgen for more informations
|
3
|
+
# Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
|
4
|
+
# This program is published under MIT license.
|
5
|
+
|
6
|
+
module PacketGen
|
7
|
+
module Header
|
8
|
+
class EAP
|
9
|
+
|
10
|
+
# Extensible Authentication Protocol (EAP) - TLS,
|
11
|
+
# {https://tools.ietf.org/html/rfc5216 RFC 5216}
|
12
|
+
#
|
13
|
+
# {EAP::TLS} has following fields:
|
14
|
+
# * {#flags} ({Types::Int8}),
|
15
|
+
# * optionally {#tls_length} ({Types::Int32}), if +#l?+ is +true+,
|
16
|
+
# * {#body} ({Types::String}).
|
17
|
+
# @author Sylvain Daubert
|
18
|
+
# @since 2.1.4
|
19
|
+
class TLS < EAP
|
20
|
+
# @!attribute flags
|
21
|
+
# @return [Integer] 8-bit flags
|
22
|
+
define_field_before :body, :flags, Types::Int8
|
23
|
+
|
24
|
+
# @!attribute l
|
25
|
+
# Say if length field is included. Defined on {#flags} field.
|
26
|
+
# @return [Boolean]
|
27
|
+
# @!attribute m
|
28
|
+
# Say if there are more fragments. Defined on {#flags} field.
|
29
|
+
# @return [Boolean]
|
30
|
+
# @!attribute s
|
31
|
+
# If set, this message is a TLS-Start. Defined on {#flags} field.
|
32
|
+
# @return [Boolean]
|
33
|
+
define_bit_fields_on :flags, :l, :m, :s, :reserved, 5
|
34
|
+
alias :length_present? :l?
|
35
|
+
alias :more_fragments? :m?
|
36
|
+
alias :tls_start? :s?
|
37
|
+
|
38
|
+
# @!attribute tls_length
|
39
|
+
# TLS message length. This field provides the total length of the
|
40
|
+
# TLS message or set of messages that is being fragmented. So, it
|
41
|
+
# cannot be automatically calculated (no +#calc_length+ method).
|
42
|
+
# @return [Integer] 32-bit TLS length
|
43
|
+
define_field_before :body, :tls_length, Types::Int32,
|
44
|
+
optional: ->(h) { h.l? }
|
45
|
+
|
46
|
+
# @return [EAP::TLS]
|
47
|
+
def initialize(options={})
|
48
|
+
super({ type: 13 }.merge!(options))
|
49
|
+
end
|
50
|
+
|
51
|
+
# @return [String]
|
52
|
+
def inspect
|
53
|
+
str = Inspect.dashed_line(self.class, 2)
|
54
|
+
fields.each do |attr|
|
55
|
+
next if attr == :body
|
56
|
+
next unless is_present?(attr)
|
57
|
+
if attr == :flags
|
58
|
+
shift = Inspect.shift_level(2)
|
59
|
+
value = %i(l m s).map { |f| send("#{f}?") ? f.to_s : '.' }.join
|
60
|
+
value = '%-10s (0x%02x)' % [value, self.flags]
|
61
|
+
str << shift
|
62
|
+
str << Inspect::FMT_ATTR % [self[attr].class.to_s.sub(/.*::/, ''),
|
63
|
+
attr, value]
|
64
|
+
else
|
65
|
+
str << Inspect.inspect_attribute(attr, self[attr], 2)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
str
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# This file is part of PacketGen
|
2
|
+
# See https://github.com/sdaubert/packetgen for more informations
|
3
|
+
# Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
|
4
|
+
# This program is published under MIT license.
|
5
|
+
|
6
|
+
module PacketGen
|
7
|
+
module Header
|
8
|
+
class EAP
|
9
|
+
|
10
|
+
# Extensible Authentication Protocol (EAP) - Tunneled-TLS,
|
11
|
+
# {https://tools.ietf.org/html/rfc5281 RFC 5281}
|
12
|
+
#
|
13
|
+
# {EAP::TTLS} has following fields:
|
14
|
+
# * {#flags} ({Types::Int8}),
|
15
|
+
# * optionally {#message_length} ({Types::Int32}), if +#l?+ is +true+,
|
16
|
+
# * {#body} ({Types::String}).
|
17
|
+
# @author Sylvain Daubert
|
18
|
+
# @since 2.1.4
|
19
|
+
class TTLS < EAP
|
20
|
+
# @!attribute flags
|
21
|
+
# @return [Integer] 8-bit flags
|
22
|
+
define_field_before :body, :flags, Types::Int8
|
23
|
+
|
24
|
+
# @!attribute l
|
25
|
+
# Say if length field is included. Defined on {#flags} field.
|
26
|
+
# @return [Boolean]
|
27
|
+
# @!attribute m
|
28
|
+
# Say if there are more fragments. Defined on {#flags} field.
|
29
|
+
# @return [Boolean]
|
30
|
+
# @!attribute s
|
31
|
+
# If set, this message is a TLS-Start. Defined on {#flags} field.
|
32
|
+
# @return [Boolean]
|
33
|
+
# @!attribute reserved
|
34
|
+
# @return [Integer] 2-bit reserved integer
|
35
|
+
# @!attribute version
|
36
|
+
# @return [Integer] 3-bit version
|
37
|
+
define_bit_fields_on :flags, :l, :m, :s, :reserved, 2, :version, 3
|
38
|
+
alias :length_present? :l?
|
39
|
+
alias :more_fragments? :m?
|
40
|
+
alias :tls_start? :s?
|
41
|
+
|
42
|
+
# @!attribute message_length
|
43
|
+
# Message length. This field provides the total length of the
|
44
|
+
# raw data message sequence prior to fragmentation. So, it
|
45
|
+
# cannot be automatically calculated (no +#calc_length+ method).
|
46
|
+
# @return [Integer] 32-bit message length
|
47
|
+
define_field_before :body, :message_length, Types::Int32,
|
48
|
+
optional: ->(h) { h.l? }
|
49
|
+
|
50
|
+
# @return [EAP::TTLS]
|
51
|
+
def initialize(options={})
|
52
|
+
super({ type: 21 }.merge!(options))
|
53
|
+
end
|
54
|
+
|
55
|
+
# @return [String]
|
56
|
+
def inspect
|
57
|
+
str = Inspect.dashed_line(self.class, 2)
|
58
|
+
fields.each do |attr|
|
59
|
+
next if attr == :body
|
60
|
+
next unless is_present?(attr)
|
61
|
+
if attr == :flags
|
62
|
+
shift = Inspect.shift_level(2)
|
63
|
+
value = %i(l m s).map { |f| send("#{f}?") ? f.to_s : '.' }.join
|
64
|
+
value = '%-10s (0x%02x)' % [value, self.flags]
|
65
|
+
str << shift
|
66
|
+
str << Inspect::FMT_ATTR % [self[attr].class.to_s.sub(/.*::/, ''),
|
67
|
+
attr, value]
|
68
|
+
str << Inspect::FMT_ATTR % ['', 'version', self.version]
|
69
|
+
else
|
70
|
+
str << Inspect.inspect_attribute(attr, self[attr], 2)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
str
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
data/lib/packetgen/header/eth.rb
CHANGED
@@ -38,27 +38,26 @@ module PacketGen
|
|
38
38
|
# Payload type number
|
39
39
|
PAYLOAD_TYPE = 39
|
40
40
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
41
|
+
METHODS = {
|
42
|
+
'RSA_SIGNATURE' => 1,
|
43
|
+
'SHARED_KEY' => 2,
|
44
|
+
'DSA_SIGNATURE' => 3,
|
45
|
+
'ECDSA256' => 9,
|
46
|
+
'ECDSA384' => 10,
|
47
|
+
'ECDSA512' => 11,
|
48
|
+
'PASSWORD' => 12,
|
49
|
+
'NULL' => 13,
|
50
|
+
'DIGITAL_SIGNATURE' => 14
|
51
|
+
}
|
50
52
|
|
51
|
-
# @attribute :u32
|
52
|
-
# 32-bit word including ID Type and RESERVED fields
|
53
|
-
# @return [Integer]
|
54
|
-
define_field_before :content, :u32, Types::Int32
|
55
53
|
# @attribute [r] method
|
56
54
|
# 8-bit Auth Method
|
57
55
|
# @return [Integer]
|
56
|
+
define_field_before :content, :method, Types::Int8Enum, enum: METHODS
|
58
57
|
# @attribute reserved
|
59
58
|
# 24-bit reserved field
|
60
59
|
# @return [Integer]
|
61
|
-
|
60
|
+
define_field_before :content, :reserved, Types::Int24
|
62
61
|
|
63
62
|
# Check authentication (see RFC 7296 §2.15)
|
64
63
|
# @param [Packet] init_msg first IKE message sent by peer
|
@@ -83,10 +82,11 @@ module PacketGen
|
|
83
82
|
signed_octets << prf(prf, sk_p, id.to_s[4, id.length - 4])
|
84
83
|
|
85
84
|
case method
|
86
|
-
when
|
85
|
+
when METHODS['SHARED_KEY']
|
87
86
|
auth = prf(prf(shared_secret, 'Key Pad for IKEv2'), signed_octets)
|
88
87
|
auth == content
|
89
|
-
when
|
88
|
+
when METHODS['RSA_SIGNATURE'], METHODS['ECDSA256'], METHODS['ECDSA384'],
|
89
|
+
METHODS['ECDSA512']
|
90
90
|
if packet.ike_cert
|
91
91
|
# FIXME: Expect a ENCODING_X509_CERT_SIG
|
92
92
|
# Others types not supported for now...
|
@@ -122,46 +122,10 @@ module PacketGen
|
|
122
122
|
end
|
123
123
|
end
|
124
124
|
|
125
|
-
# Set Auth method
|
126
|
-
# @param [Integer,String] value
|
127
|
-
# @return [Integer]
|
128
|
-
def method=(value)
|
129
|
-
method = case value
|
130
|
-
when Integer
|
131
|
-
value
|
132
|
-
else
|
133
|
-
c = self.class.constants.grep(/METHOD_#{value}/).first
|
134
|
-
c ? self.class.const_get(c) : nil
|
135
|
-
end
|
136
|
-
raise ArgumentError, "unknown auth method #{value.inspect}" unless method
|
137
|
-
self[:u32].value = (self[:u32].to_i & 0xffffff) | (method << 24)
|
138
|
-
end
|
139
|
-
|
140
125
|
# Get authentication method name
|
141
126
|
# @return [String]
|
142
127
|
def human_method
|
143
|
-
|
144
|
-
select { |c| self.class.const_get(c) == method }.
|
145
|
-
first || "method #{method}"
|
146
|
-
name.to_s.sub(/METHOD_/, '')
|
147
|
-
end
|
148
|
-
|
149
|
-
# @return [String]
|
150
|
-
def inspect
|
151
|
-
str = Inspect.dashed_line(self.class, 2)
|
152
|
-
fields.each do |attr|
|
153
|
-
case attr
|
154
|
-
when :body
|
155
|
-
next
|
156
|
-
when :u32
|
157
|
-
str << Inspect.shift_level(2)
|
158
|
-
str << Inspect::FMT_ATTR % ['Int8', :method, human_method]
|
159
|
-
str << Inspect.inspect_attribute(:reserved, self.reserved, 2)
|
160
|
-
else
|
161
|
-
str << Inspect.inspect_attribute(attr, self[attr], 2)
|
162
|
-
end
|
163
|
-
end
|
164
|
-
str
|
128
|
+
self[:method].to_human
|
165
129
|
end
|
166
130
|
|
167
131
|
private
|
@@ -40,80 +40,43 @@ module PacketGen
|
|
40
40
|
# Payload type number
|
41
41
|
PAYLOAD_TYPE = 35
|
42
42
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
43
|
+
TYPES = {
|
44
|
+
'IPV4_ADDR' => 1,
|
45
|
+
'FQDN' => 2,
|
46
|
+
'RFC822_ADDR' => 3,
|
47
|
+
'IPV6_ADDR' => 5,
|
48
|
+
'DER_ASN1_DN' => 9,
|
49
|
+
'DER_ASN1_GN' => 10,
|
50
|
+
'KEY_ID' => 11
|
51
|
+
}
|
50
52
|
|
51
|
-
# @attribute :u32
|
52
|
-
# 32-bit word including ID Type and RESERVED fields
|
53
|
-
# @return [Integer]
|
54
|
-
define_field_before :content, :u32, Types::Int32
|
55
53
|
# @attribute [r] type
|
56
54
|
# 8-bit ID type
|
57
55
|
# @return [Integer]
|
56
|
+
define_field_before :content, :type, Types::Int8Enum, enum: TYPES
|
58
57
|
# @attribute reserved
|
59
58
|
# 24-bit reserved field
|
60
59
|
# @return [Integer]
|
61
|
-
|
62
|
-
|
63
|
-
# Set ID type
|
64
|
-
# @param [Integer,String] value
|
65
|
-
# @return [Integer]
|
66
|
-
def type=(value)
|
67
|
-
type = case value
|
68
|
-
when Integer
|
69
|
-
value
|
70
|
-
else
|
71
|
-
c = self.class.constants.grep(/TYPE_#{value}/).first
|
72
|
-
c ? self.class.const_get(c) : nil
|
73
|
-
end
|
74
|
-
raise ArgumentError, "unknown ID type #{value.inspect}" unless type
|
75
|
-
self[:u32].value = (self[:u32].to_i & 0xffffff) | (type << 24)
|
76
|
-
end
|
60
|
+
define_field_before :content, :reserved, Types::Int24
|
77
61
|
|
78
62
|
# Get ID type name
|
79
63
|
# @return [String]
|
80
64
|
def human_type
|
81
|
-
|
82
|
-
select { |c| self.class.const_get(c) == type }.
|
83
|
-
first || "type #{type}"
|
84
|
-
name.to_s.sub(/TYPE_/, '')
|
65
|
+
self[:type].to_human
|
85
66
|
end
|
86
67
|
|
87
68
|
# Get human readable content, from {#type}
|
88
69
|
# @return [String]
|
89
70
|
def human_content
|
90
71
|
case type
|
91
|
-
when
|
72
|
+
when TYPES['IPV4_ADDR'], TYPES['IPV4_ADDR']
|
92
73
|
IPAddr.ntop(content)
|
93
|
-
when
|
74
|
+
when TYPES['DER_ASN1_DN'], TYPES['DER_ASN1_GN']
|
94
75
|
OpenSSL::X509::Name.new(content).to_s
|
95
76
|
else
|
96
77
|
content.inspect
|
97
78
|
end
|
98
79
|
end
|
99
|
-
|
100
|
-
# @return [String]
|
101
|
-
def inspect
|
102
|
-
str = Inspect.dashed_line(self.class, 2)
|
103
|
-
fields.each do |attr|
|
104
|
-
case attr
|
105
|
-
when :body
|
106
|
-
next
|
107
|
-
when :u32
|
108
|
-
str << Inspect.shift_level(2)
|
109
|
-
str << Inspect::FMT_ATTR % ['Int8', :type, human_type]
|
110
|
-
str << Inspect.inspect_attribute(:reserved, self.reserved, 2)
|
111
|
-
else
|
112
|
-
str << Inspect.inspect_attribute(attr, self[attr], 2)
|
113
|
-
end
|
114
|
-
end
|
115
|
-
str
|
116
|
-
end
|
117
80
|
end
|
118
81
|
|
119
82
|
# This class handles Identification - Responder payloads, denoted IDr.
|
@@ -225,14 +225,10 @@ module PacketGen
|
|
225
225
|
# 8-bit Number of TSs
|
226
226
|
# @return [Integer]
|
227
227
|
define_field_before :body, :num_ts, Types::Int8
|
228
|
-
# @!attribute
|
229
|
-
#
|
228
|
+
# @!attribute rsv
|
229
|
+
# 24-bit RESERVED field
|
230
230
|
# @return [Integer]
|
231
|
-
define_field_before :body, :
|
232
|
-
# @!attribute rsv2
|
233
|
-
# Last 16-bit RESERVED field
|
234
|
-
# @return [Integer]
|
235
|
-
define_field_before :body, :rsv2, Types::Int16
|
231
|
+
define_field_before :body, :rsv, Types::Int24
|
236
232
|
|
237
233
|
# @!attribute traffic_selectors
|
238
234
|
# Set of {TrafficSelector}
|
@@ -259,24 +255,6 @@ module PacketGen
|
|
259
255
|
selectors.each { |p| p.calc_length }
|
260
256
|
super
|
261
257
|
end
|
262
|
-
|
263
|
-
# @return [String]
|
264
|
-
def inspect
|
265
|
-
str = Inspect.dashed_line(self.class, 2)
|
266
|
-
fields.each do |attr|
|
267
|
-
case attr
|
268
|
-
when :body, :rsv2
|
269
|
-
next
|
270
|
-
when :rsv1
|
271
|
-
str << Inspect.shift_level(2)
|
272
|
-
str << Inspect::FMT_ATTR % ['Int24', 'reserved',
|
273
|
-
(rsv1 << 16) | rsv2 ]
|
274
|
-
else
|
275
|
-
str << Inspect.inspect_attribute(attr, self[attr], 2)
|
276
|
-
end
|
277
|
-
end
|
278
|
-
str
|
279
|
-
end
|
280
258
|
end
|
281
259
|
|
282
260
|
class TSr < TSi
|
data/lib/packetgen/header/ip.rb
CHANGED
data/lib/packetgen/inspect.rb
CHANGED
@@ -49,8 +49,10 @@ module PacketGen
|
|
49
49
|
# @return [String]
|
50
50
|
def self.inspect_attribute(attr, value, level=1)
|
51
51
|
str = shift_level(level)
|
52
|
-
val = if value.is_a?(Types::
|
53
|
-
|
52
|
+
val = if value.is_a?(Types::Enum)
|
53
|
+
"%-10s (0x%0#{value.sz * 2}x)" % [value.to_human, value.to_i]
|
54
|
+
elsif value.is_a?(Types::Int) or value.is_a?(Integer)
|
55
|
+
int_dec_hex(value, value.sz * 2)
|
54
56
|
elsif value.respond_to? :to_human
|
55
57
|
value.to_human
|
56
58
|
else
|
data/lib/packetgen/packet.rb
CHANGED
@@ -209,11 +209,23 @@ module PacketGen
|
|
209
209
|
|
210
210
|
# send packet on wire. Use first header +#to_w+ method.
|
211
211
|
# @param [String] iface interface name. Default to first non-loopback interface
|
212
|
+
# @param [Boolean] calc call {#calc} on packet before sending it
|
213
|
+
# @param [Integer] number number of times to send the packets
|
214
|
+
# @param [Integer,Float] interval time, in seconds, between sending 2 packets
|
212
215
|
# @return [void]
|
213
|
-
|
216
|
+
# @since 2.1.4 add `calc`, `number` and `interval` parameters
|
217
|
+
def to_w(iface=nil, calc: false, number: 1, interval: 1)
|
214
218
|
iface ||= PacketGen.default_iface
|
215
219
|
if @headers.first.respond_to? :to_w
|
216
|
-
|
220
|
+
self.calc if calc
|
221
|
+
if number == 1
|
222
|
+
@headers.first.to_w(iface)
|
223
|
+
else
|
224
|
+
number.times do
|
225
|
+
@headers.first.to_w(iface)
|
226
|
+
sleep interval
|
227
|
+
end
|
228
|
+
end
|
217
229
|
else
|
218
230
|
type = @headers.first.protocol_name
|
219
231
|
raise WireError, "don't known how to send a #{type} packet on wire"
|
@@ -360,8 +372,8 @@ module PacketGen
|
|
360
372
|
header.packet = self
|
361
373
|
@headers << header unless previous_header
|
362
374
|
unless respond_to? header.method_name
|
363
|
-
self.
|
364
|
-
|
375
|
+
self.instance_eval "def #{header.method_name}(arg=nil);" \
|
376
|
+
"header(#{header.class}, arg); end"
|
365
377
|
end
|
366
378
|
end
|
367
379
|
|
@@ -151,9 +151,6 @@ module PacketGen
|
|
151
151
|
end
|
152
152
|
|
153
153
|
# Translates a {File} into an array of packets.
|
154
|
-
# Note that this strips out timestamps -- if you'd like to retain
|
155
|
-
# timestamps and other pcapng file information, you will want to
|
156
|
-
# use {#read} instead.
|
157
154
|
# @param [Hash] options
|
158
155
|
# @option options [String] :filename if given, object is cleared and filename
|
159
156
|
# is analyzed before generating array. Else, array is generated from +self+
|
@@ -293,34 +293,35 @@ module PacketGen
|
|
293
293
|
@optional_fields = {}
|
294
294
|
|
295
295
|
self.class.class_eval { @field_defs }.each do |field, ary|
|
296
|
-
default
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
296
|
+
type, default, builder, optional, enum, field_options = ary
|
297
|
+
default = default.call if default.is_a?(Proc)
|
298
|
+
@fields[field] = if builder
|
299
|
+
builder.call(self)
|
300
|
+
elsif enum
|
301
|
+
type.new(enum)
|
302
|
+
elsif !field_options.empty?
|
303
|
+
type.new(field_options)
|
303
304
|
else
|
304
|
-
|
305
|
+
type.new
|
305
306
|
end
|
306
307
|
|
307
308
|
value = options[field] || default
|
308
|
-
if
|
309
|
+
if type < Types::Enum
|
309
310
|
case value
|
310
311
|
when ::String
|
311
312
|
@fields[field].value = value
|
312
313
|
else
|
313
314
|
@fields[field].read(value)
|
314
315
|
end
|
315
|
-
elsif
|
316
|
+
elsif type < Types::Int
|
316
317
|
@fields[field].read(value)
|
317
|
-
elsif
|
318
|
+
elsif type <= Types::String
|
318
319
|
@fields[field].read(value)
|
319
320
|
else
|
320
321
|
@fields[field].from_human(value) if @fields[field].respond_to? :from_human
|
321
322
|
end
|
322
323
|
|
323
|
-
@optional_fields[field] =
|
324
|
+
@optional_fields[field] = optional if optional
|
324
325
|
end
|
325
326
|
self.class.class_eval { @bit_fields }.each do |bit_field|
|
326
327
|
self.send "#{bit_field}=", options[bit_field] if options[bit_field]
|
@@ -350,7 +351,7 @@ module PacketGen
|
|
350
351
|
|
351
352
|
# Get all optional field name
|
352
353
|
def optional_fields
|
353
|
-
|
354
|
+
@optional_fields.keys
|
354
355
|
end
|
355
356
|
|
356
357
|
# Say if this field is optional
|
data/lib/packetgen/types/int.rb
CHANGED
@@ -117,6 +117,67 @@ module PacketGen
|
|
117
117
|
end
|
118
118
|
end
|
119
119
|
|
120
|
+
# 3-byte integer
|
121
|
+
# @author Sylvain Daubert
|
122
|
+
# @since 2.1.4
|
123
|
+
class Int24 < Int
|
124
|
+
# @param [Integer,nil] value
|
125
|
+
# @param [:big, :little] endian
|
126
|
+
def initialize(value=nil, endian=:big)
|
127
|
+
super(value, endian, 3)
|
128
|
+
end
|
129
|
+
|
130
|
+
# Read an 3-byte Int from a binary string or an integer
|
131
|
+
# @param [Integer, String] value
|
132
|
+
# @return [self]
|
133
|
+
def read(value)
|
134
|
+
return self if value.nil?
|
135
|
+
@value = if value.is_a?(Integer)
|
136
|
+
value.to_i
|
137
|
+
else
|
138
|
+
up8 = down16 = 0
|
139
|
+
if @endian == :big
|
140
|
+
up8, down16 = value.to_s.unpack('Cn')
|
141
|
+
else
|
142
|
+
down16, up8 = value.to_s.unpack('vC')
|
143
|
+
end
|
144
|
+
(up8 << 16) | down16
|
145
|
+
end
|
146
|
+
self
|
147
|
+
end
|
148
|
+
|
149
|
+
# @return [::String]
|
150
|
+
def to_s
|
151
|
+
up8 = to_i >> 16
|
152
|
+
down16 = to_i & 0xffff
|
153
|
+
if @endian == :little
|
154
|
+
[up8, down16].pack('Cn')
|
155
|
+
else
|
156
|
+
[down16, up8].pack('vC')
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
# big endian 3-byte integer
|
162
|
+
# @author Sylvain Daubert
|
163
|
+
# @since 2.1.4
|
164
|
+
class Int24be < Int24
|
165
|
+
undef endian=
|
166
|
+
end
|
167
|
+
|
168
|
+
# little endian 3-byte integer
|
169
|
+
# @author Sylvain Daubert
|
170
|
+
# @since 2.1.4
|
171
|
+
class Int24le < Int24
|
172
|
+
# @param [Integer,nil] value
|
173
|
+
undef endian=
|
174
|
+
|
175
|
+
# @param [Integer, nil] value
|
176
|
+
def initialize(value=nil)
|
177
|
+
super(value, :little)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
120
181
|
# 4-byte integer
|
121
182
|
# @author Sylvain Daubert
|
122
183
|
class Int32 < Int
|
data/lib/packetgen/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: packetgen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.
|
4
|
+
version: 2.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sylvain Daubert
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-11-
|
11
|
+
date: 2017-11-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pcaprub
|
@@ -167,6 +167,11 @@ files:
|
|
167
167
|
- lib/packetgen/header/dot11/sub_mngt.rb
|
168
168
|
- lib/packetgen/header/dot1q.rb
|
169
169
|
- lib/packetgen/header/dot1x.rb
|
170
|
+
- lib/packetgen/header/eap.rb
|
171
|
+
- lib/packetgen/header/eap/fast.rb
|
172
|
+
- lib/packetgen/header/eap/md5.rb
|
173
|
+
- lib/packetgen/header/eap/tls.rb
|
174
|
+
- lib/packetgen/header/eap/ttls.rb
|
170
175
|
- lib/packetgen/header/esp.rb
|
171
176
|
- lib/packetgen/header/eth.rb
|
172
177
|
- lib/packetgen/header/gre.rb
|