packetgen 2.1.3 → 2.1.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|