packetgen 1.4.3 → 2.0.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.
@@ -0,0 +1,307 @@
1
+ module PacketGen
2
+ module Header
3
+ class IKE
4
+
5
+ # Base class for IKE payloads. This class may also be used for unknown payloads.
6
+ #
7
+ # This class handles generic IKE payload header:
8
+ # 1 2 3
9
+ # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
10
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
11
+ # | Next Payload |C| RESERVED | Payload Length |
12
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
13
+ # to which a {#content} field is added to handle content of unknown payload types.
14
+ # @author Sylvain Daubert
15
+ class Payload < Base
16
+ # @!attribute next
17
+ # 8-bit next payload
18
+ # @return [Integer]
19
+ define_field :next, Types::Int8
20
+ # @!attribute flags
21
+ # 8-bit flags
22
+ # @return [Integer]
23
+ define_field :flags, Types::Int8
24
+ # @!attribute length
25
+ # 16-bit payload total length, including generic payload header
26
+ # @return [Integer]
27
+ define_field :length, Types::Int16
28
+ # @!attribute content
29
+ # Payload content. Depends on payload. Variable length.
30
+ # @return [String]
31
+ define_field :content, Types::String
32
+
33
+ # Defining a body permits using Packet#parse to parse next IKE payloads.
34
+ define_field :body, Types::String
35
+
36
+ # @!attribute critical
37
+ # critical flag
38
+ # @return [Boolean]
39
+ # @!attribute hreserved
40
+ # reserved part of {#flags} field
41
+ # @return [Integer]
42
+ define_bit_fields_on :flags, :critical, :hreserved, 7
43
+
44
+ def initialize(options={})
45
+ super
46
+ self[:length].value = sz unless options[:length]
47
+ end
48
+
49
+ # @private
50
+ alias base_read read
51
+
52
+ # Populate object from a string
53
+ # @param [String] str
54
+ # @return [self]
55
+ def read(str)
56
+ base_read str
57
+ unless self[:content].nil?
58
+ content_length = length - self.class.new.sz
59
+ if content_length >= 0
60
+ self[:body] = self[:content][content_length..-1]
61
+ self[:content] = self[:content][0, content_length]
62
+ end
63
+ end
64
+ self
65
+ end
66
+
67
+ # Compute length and set {#length} field
68
+ # @return [Integer] new length
69
+ def calc_length
70
+ self[:length].value = sz - body.sz
71
+ end
72
+ end
73
+ end
74
+
75
+ self.add_class IKE::Payload
76
+ end
77
+ end
78
+
79
+ # here, future payloads to be required
80
+ require_relative 'sa'
81
+ require_relative 'ke'
82
+ require_relative 'nonce'
83
+ require_relative 'notify'
84
+ require_relative 'sk'
85
+ require_relative 'id'
86
+ require_relative 'cert'
87
+ require_relative 'certreq'
88
+ require_relative 'auth'
89
+ require_relative 'ts'
90
+ require_relative 'vendor_id'
91
+
92
+ module PacketGen
93
+ module Header
94
+ IKE.bind_header IKE::SA, next: IKE::SA::PAYLOAD_TYPE
95
+ IKE::Payload.bind_header IKE::SA, next: IKE::SA::PAYLOAD_TYPE
96
+ IKE::KE.bind_header IKE::SA, next: IKE::SA::PAYLOAD_TYPE
97
+ IKE::Nonce.bind_header IKE::SA, next: IKE::SA::PAYLOAD_TYPE
98
+ IKE::Notify.bind_header IKE::SA, next: IKE::SA::PAYLOAD_TYPE
99
+ IKE::SK.bind_header IKE::SA, next: IKE::SA::PAYLOAD_TYPE
100
+ IKE::IDi.bind_header IKE::SA, next: IKE::SA::PAYLOAD_TYPE
101
+ IKE::IDr.bind_header IKE::SA, next: IKE::SA::PAYLOAD_TYPE
102
+ IKE::Cert.bind_header IKE::SA, next: IKE::SA::PAYLOAD_TYPE
103
+ IKE::CertReq.bind_header IKE::SA, next: IKE::SA::PAYLOAD_TYPE
104
+ IKE::Auth.bind_header IKE::SA, next: IKE::SA::PAYLOAD_TYPE
105
+ IKE::TSi.bind_header IKE::SA, next: IKE::SA::PAYLOAD_TYPE
106
+ IKE::TSr.bind_header IKE::SA, next: IKE::SA::PAYLOAD_TYPE
107
+ IKE::VendorID.bind_header IKE::SA, next: IKE::SA::PAYLOAD_TYPE
108
+
109
+ IKE.bind_header IKE::KE, next: IKE::KE::PAYLOAD_TYPE
110
+ IKE::Payload.bind_header IKE::KE, next: IKE::KE::PAYLOAD_TYPE
111
+ IKE::SA.bind_header IKE::KE, next: IKE::KE::PAYLOAD_TYPE
112
+ IKE::Nonce.bind_header IKE::KE, next: IKE::KE::PAYLOAD_TYPE
113
+ IKE::Notify.bind_header IKE::KE, next: IKE::KE::PAYLOAD_TYPE
114
+ IKE::SK.bind_header IKE::KE, next: IKE::KE::PAYLOAD_TYPE
115
+ IKE::IDi.bind_header IKE::KE, next: IKE::KE::PAYLOAD_TYPE
116
+ IKE::IDr.bind_header IKE::KE, next: IKE::KE::PAYLOAD_TYPE
117
+ IKE::Cert.bind_header IKE::KE, next: IKE::KE::PAYLOAD_TYPE
118
+ IKE::CertReq.bind_header IKE::KE, next: IKE::KE::PAYLOAD_TYPE
119
+ IKE::Auth.bind_header IKE::KE, next: IKE::KE::PAYLOAD_TYPE
120
+ IKE::TSi.bind_header IKE::KE, next: IKE::KE::PAYLOAD_TYPE
121
+ IKE::TSr.bind_header IKE::KE, next: IKE::KE::PAYLOAD_TYPE
122
+ IKE::VendorID.bind_header IKE::KE, next: IKE::KE::PAYLOAD_TYPE
123
+
124
+ IKE.bind_header IKE::Nonce, next: IKE::Nonce::PAYLOAD_TYPE
125
+ IKE::Payload.bind_header IKE::Nonce, next: IKE::Nonce::PAYLOAD_TYPE
126
+ IKE::SA.bind_header IKE::Nonce, next: IKE::Nonce::PAYLOAD_TYPE
127
+ IKE::KE.bind_header IKE::Nonce, next: IKE::Nonce::PAYLOAD_TYPE
128
+ IKE::Notify.bind_header IKE::Nonce, next: IKE::Nonce::PAYLOAD_TYPE
129
+ IKE::SK.bind_header IKE::Nonce, next: IKE::Nonce::PAYLOAD_TYPE
130
+ IKE::IDi.bind_header IKE::Nonce, next: IKE::Nonce::PAYLOAD_TYPE
131
+ IKE::IDr.bind_header IKE::Nonce, next: IKE::Nonce::PAYLOAD_TYPE
132
+ IKE::Cert.bind_header IKE::Nonce, next: IKE::Nonce::PAYLOAD_TYPE
133
+ IKE::CertReq.bind_header IKE::Nonce, next: IKE::Nonce::PAYLOAD_TYPE
134
+ IKE::Auth.bind_header IKE::Nonce, next: IKE::Nonce::PAYLOAD_TYPE
135
+ IKE::TSi.bind_header IKE::Nonce, next: IKE::Nonce::PAYLOAD_TYPE
136
+ IKE::TSr.bind_header IKE::Nonce, next: IKE::Nonce::PAYLOAD_TYPE
137
+ IKE::VendorID.bind_header IKE::Nonce, next: IKE::Nonce::PAYLOAD_TYPE
138
+
139
+ IKE.bind_header IKE::Notify, next: IKE::Notify::PAYLOAD_TYPE
140
+ IKE::Payload.bind_header IKE::Notify, next: IKE::Notify::PAYLOAD_TYPE
141
+ IKE::SA.bind_header IKE::Notify, next: IKE::Notify::PAYLOAD_TYPE
142
+ IKE::KE.bind_header IKE::Notify, next: IKE::Notify::PAYLOAD_TYPE
143
+ IKE::Nonce.bind_header IKE::Notify, next: IKE::Notify::PAYLOAD_TYPE
144
+ IKE::Notify.bind_header IKE::Notify, next: IKE::Notify::PAYLOAD_TYPE
145
+ IKE::SK.bind_header IKE::Notify, next: IKE::Notify::PAYLOAD_TYPE
146
+ IKE::IDi.bind_header IKE::Notify, next: IKE::Notify::PAYLOAD_TYPE
147
+ IKE::IDr.bind_header IKE::Notify, next: IKE::Notify::PAYLOAD_TYPE
148
+ IKE::Cert.bind_header IKE::Notify, next: IKE::Notify::PAYLOAD_TYPE
149
+ IKE::CertReq.bind_header IKE::Notify, next: IKE::Notify::PAYLOAD_TYPE
150
+ IKE::Auth.bind_header IKE::Notify, next: IKE::Notify::PAYLOAD_TYPE
151
+ IKE::TSi.bind_header IKE::Notify, next: IKE::Notify::PAYLOAD_TYPE
152
+ IKE::TSr.bind_header IKE::Notify, next: IKE::Notify::PAYLOAD_TYPE
153
+ IKE::VendorID.bind_header IKE::Notify, next: IKE::Notify::PAYLOAD_TYPE
154
+
155
+ IKE.bind_header IKE::SK, next: IKE::SK::PAYLOAD_TYPE
156
+ IKE::Payload.bind_header IKE::SK, next: IKE::SK::PAYLOAD_TYPE
157
+ IKE::SA.bind_header IKE::SK, next: IKE::SK::PAYLOAD_TYPE
158
+ IKE::KE.bind_header IKE::SK, next: IKE::SK::PAYLOAD_TYPE
159
+ IKE::Nonce.bind_header IKE::SK, next: IKE::SK::PAYLOAD_TYPE
160
+ IKE::Notify.bind_header IKE::SK, next: IKE::SK::PAYLOAD_TYPE
161
+ IKE::IDi.bind_header IKE::SK, next: IKE::SK::PAYLOAD_TYPE
162
+ IKE::IDr.bind_header IKE::SK, next: IKE::SK::PAYLOAD_TYPE
163
+ IKE::Cert.bind_header IKE::SK, next: IKE::SK::PAYLOAD_TYPE
164
+ IKE::CertReq.bind_header IKE::SK, next: IKE::SK::PAYLOAD_TYPE
165
+ IKE::Auth.bind_header IKE::SK, next: IKE::SK::PAYLOAD_TYPE
166
+ IKE::TSi.bind_header IKE::SK, next: IKE::SK::PAYLOAD_TYPE
167
+ IKE::TSr.bind_header IKE::SK, next: IKE::SK::PAYLOAD_TYPE
168
+ IKE::VendorID.bind_header IKE::SK, next: IKE::SK::PAYLOAD_TYPE
169
+
170
+ IKE.bind_header IKE::IDi, next: IKE::IDi::PAYLOAD_TYPE
171
+ IKE::Payload.bind_header IKE::IDi, next: IKE::IDi::PAYLOAD_TYPE
172
+ IKE::SA.bind_header IKE::IDi, next: IKE::IDi::PAYLOAD_TYPE
173
+ IKE::KE.bind_header IKE::IDi, next: IKE::IDi::PAYLOAD_TYPE
174
+ IKE::Nonce.bind_header IKE::IDi, next: IKE::IDi::PAYLOAD_TYPE
175
+ IKE::Notify.bind_header IKE::IDi, next: IKE::IDi::PAYLOAD_TYPE
176
+ IKE::SK.bind_header IKE::IDi, next: IKE::IDi::PAYLOAD_TYPE
177
+ IKE::IDr.bind_header IKE::IDi, next: IKE::IDi::PAYLOAD_TYPE
178
+ IKE::Cert.bind_header IKE::IDi, next: IKE::IDi::PAYLOAD_TYPE
179
+ IKE::CertReq.bind_header IKE::IDi, next: IKE::IDi::PAYLOAD_TYPE
180
+ IKE::Auth.bind_header IKE::IDi, next: IKE::IDi::PAYLOAD_TYPE
181
+ IKE::TSi.bind_header IKE::IDi, next: IKE::IDi::PAYLOAD_TYPE
182
+ IKE::TSr.bind_header IKE::IDi, next: IKE::IDi::PAYLOAD_TYPE
183
+ IKE::VendorID.bind_header IKE::IDi, next: IKE::IDi::PAYLOAD_TYPE
184
+
185
+ IKE.bind_header IKE::IDr, next: IKE::IDr::PAYLOAD_TYPE
186
+ IKE::Payload.bind_header IKE::IDr, next: IKE::IDr::PAYLOAD_TYPE
187
+ IKE::SA.bind_header IKE::IDr, next: IKE::IDr::PAYLOAD_TYPE
188
+ IKE::KE.bind_header IKE::IDr, next: IKE::IDr::PAYLOAD_TYPE
189
+ IKE::Nonce.bind_header IKE::IDr, next: IKE::IDr::PAYLOAD_TYPE
190
+ IKE::Notify.bind_header IKE::IDr, next: IKE::IDr::PAYLOAD_TYPE
191
+ IKE::SK.bind_header IKE::IDr, next: IKE::IDr::PAYLOAD_TYPE
192
+ IKE::IDi.bind_header IKE::IDr, next: IKE::IDr::PAYLOAD_TYPE
193
+ IKE::Cert.bind_header IKE::IDr, next: IKE::IDr::PAYLOAD_TYPE
194
+ IKE::CertReq.bind_header IKE::IDr, next: IKE::IDr::PAYLOAD_TYPE
195
+ IKE::Auth.bind_header IKE::IDr, next: IKE::IDr::PAYLOAD_TYPE
196
+ IKE::TSi.bind_header IKE::IDr, next: IKE::IDr::PAYLOAD_TYPE
197
+ IKE::TSr.bind_header IKE::IDr, next: IKE::IDr::PAYLOAD_TYPE
198
+ IKE::VendorID.bind_header IKE::IDr, next: IKE::IDr::PAYLOAD_TYPE
199
+
200
+ IKE.bind_header IKE::Cert, next: IKE::Cert::PAYLOAD_TYPE
201
+ IKE::Payload.bind_header IKE::Cert, next: IKE::Cert::PAYLOAD_TYPE
202
+ IKE::SA.bind_header IKE::Cert, next: IKE::Cert::PAYLOAD_TYPE
203
+ IKE::KE.bind_header IKE::Cert, next: IKE::Cert::PAYLOAD_TYPE
204
+ IKE::Nonce.bind_header IKE::Cert, next: IKE::Cert::PAYLOAD_TYPE
205
+ IKE::Notify.bind_header IKE::Cert, next: IKE::Cert::PAYLOAD_TYPE
206
+ IKE::SK.bind_header IKE::Cert, next: IKE::Cert::PAYLOAD_TYPE
207
+ IKE::IDi.bind_header IKE::Cert, next: IKE::Cert::PAYLOAD_TYPE
208
+ IKE::IDr.bind_header IKE::Cert, next: IKE::Cert::PAYLOAD_TYPE
209
+ IKE::CertReq.bind_header IKE::Cert, next: IKE::Cert::PAYLOAD_TYPE
210
+ IKE::Auth.bind_header IKE::Cert, next: IKE::Cert::PAYLOAD_TYPE
211
+ IKE::TSi.bind_header IKE::Cert, next: IKE::Cert::PAYLOAD_TYPE
212
+ IKE::TSr.bind_header IKE::Cert, next: IKE::Cert::PAYLOAD_TYPE
213
+ IKE::VendorID.bind_header IKE::Cert, next: IKE::Cert::PAYLOAD_TYPE
214
+
215
+ IKE.bind_header IKE::CertReq, next: IKE::CertReq::PAYLOAD_TYPE
216
+ IKE::Payload.bind_header IKE::CertReq, next: IKE::CertReq::PAYLOAD_TYPE
217
+ IKE::SA.bind_header IKE::CertReq, next: IKE::CertReq::PAYLOAD_TYPE
218
+ IKE::KE.bind_header IKE::CertReq, next: IKE::CertReq::PAYLOAD_TYPE
219
+ IKE::Nonce.bind_header IKE::CertReq, next: IKE::CertReq::PAYLOAD_TYPE
220
+ IKE::Notify.bind_header IKE::CertReq, next: IKE::CertReq::PAYLOAD_TYPE
221
+ IKE::SK.bind_header IKE::CertReq, next: IKE::CertReq::PAYLOAD_TYPE
222
+ IKE::IDi.bind_header IKE::CertReq, next: IKE::CertReq::PAYLOAD_TYPE
223
+ IKE::IDr.bind_header IKE::CertReq, next: IKE::CertReq::PAYLOAD_TYPE
224
+ IKE::Cert.bind_header IKE::CertReq, next: IKE::CertReq::PAYLOAD_TYPE
225
+ IKE::Auth.bind_header IKE::CertReq, next: IKE::CertReq::PAYLOAD_TYPE
226
+ IKE::TSi.bind_header IKE::CertReq, next: IKE::CertReq::PAYLOAD_TYPE
227
+ IKE::TSr.bind_header IKE::CertReq, next: IKE::CertReq::PAYLOAD_TYPE
228
+ IKE::VendorID.bind_header IKE::CertReq, next: IKE::CertReq::PAYLOAD_TYPE
229
+
230
+ IKE.bind_header IKE::Auth, next: IKE::Auth::PAYLOAD_TYPE
231
+ IKE::Payload.bind_header IKE::Auth, next: IKE::Auth::PAYLOAD_TYPE
232
+ IKE::SA.bind_header IKE::Auth, next: IKE::Auth::PAYLOAD_TYPE
233
+ IKE::KE.bind_header IKE::Auth, next: IKE::Auth::PAYLOAD_TYPE
234
+ IKE::Nonce.bind_header IKE::Auth, next: IKE::Auth::PAYLOAD_TYPE
235
+ IKE::Notify.bind_header IKE::Auth, next: IKE::Auth::PAYLOAD_TYPE
236
+ IKE::SK.bind_header IKE::Auth, next: IKE::Auth::PAYLOAD_TYPE
237
+ IKE::IDi.bind_header IKE::Auth, next: IKE::Auth::PAYLOAD_TYPE
238
+ IKE::IDr.bind_header IKE::Auth, next: IKE::Auth::PAYLOAD_TYPE
239
+ IKE::Cert.bind_header IKE::Auth, next: IKE::Auth::PAYLOAD_TYPE
240
+ IKE::CertReq.bind_header IKE::Auth, next: IKE::Auth::PAYLOAD_TYPE
241
+ IKE::TSi.bind_header IKE::Auth, next: IKE::Auth::PAYLOAD_TYPE
242
+ IKE::TSr.bind_header IKE::Auth, next: IKE::Auth::PAYLOAD_TYPE
243
+ IKE::VendorID.bind_header IKE::Auth, next: IKE::Auth::PAYLOAD_TYPE
244
+
245
+ IKE.bind_header IKE::TSi, next: IKE::TSi::PAYLOAD_TYPE
246
+ IKE::Payload.bind_header IKE::TSi, next: IKE::TSi::PAYLOAD_TYPE
247
+ IKE::SA.bind_header IKE::TSi, next: IKE::TSi::PAYLOAD_TYPE
248
+ IKE::KE.bind_header IKE::TSi, next: IKE::TSi::PAYLOAD_TYPE
249
+ IKE::Nonce.bind_header IKE::TSi, next: IKE::TSi::PAYLOAD_TYPE
250
+ IKE::Notify.bind_header IKE::TSi, next: IKE::TSi::PAYLOAD_TYPE
251
+ IKE::SK.bind_header IKE::TSi, next: IKE::TSi::PAYLOAD_TYPE
252
+ IKE::IDi.bind_header IKE::TSi, next: IKE::TSi::PAYLOAD_TYPE
253
+ IKE::IDr.bind_header IKE::TSi, next: IKE::TSi::PAYLOAD_TYPE
254
+ IKE::Cert.bind_header IKE::TSi, next: IKE::TSi::PAYLOAD_TYPE
255
+ IKE::CertReq.bind_header IKE::TSi, next: IKE::TSi::PAYLOAD_TYPE
256
+ IKE::Auth.bind_header IKE::TSi, next: IKE::TSi::PAYLOAD_TYPE
257
+ IKE::TSr.bind_header IKE::TSi, next: IKE::TSi::PAYLOAD_TYPE
258
+ IKE::VendorID.bind_header IKE::TSi, next: IKE::TSi::PAYLOAD_TYPE
259
+
260
+ IKE.bind_header IKE::TSr, next: IKE::TSr::PAYLOAD_TYPE
261
+ IKE::Payload.bind_header IKE::TSr, next: IKE::TSr::PAYLOAD_TYPE
262
+ IKE::SA.bind_header IKE::TSr, next: IKE::TSr::PAYLOAD_TYPE
263
+ IKE::KE.bind_header IKE::TSr, next: IKE::TSr::PAYLOAD_TYPE
264
+ IKE::Nonce.bind_header IKE::TSr, next: IKE::TSr::PAYLOAD_TYPE
265
+ IKE::Notify.bind_header IKE::TSr, next: IKE::TSr::PAYLOAD_TYPE
266
+ IKE::SK.bind_header IKE::TSr, next: IKE::TSr::PAYLOAD_TYPE
267
+ IKE::IDi.bind_header IKE::TSr, next: IKE::TSr::PAYLOAD_TYPE
268
+ IKE::IDr.bind_header IKE::TSr, next: IKE::TSr::PAYLOAD_TYPE
269
+ IKE::Cert.bind_header IKE::TSr, next: IKE::TSr::PAYLOAD_TYPE
270
+ IKE::CertReq.bind_header IKE::TSr, next: IKE::TSr::PAYLOAD_TYPE
271
+ IKE::Auth.bind_header IKE::TSr, next: IKE::TSr::PAYLOAD_TYPE
272
+ IKE::TSi.bind_header IKE::TSr, next: IKE::TSr::PAYLOAD_TYPE
273
+ IKE::VendorID.bind_header IKE::TSr, next: IKE::TSr::PAYLOAD_TYPE
274
+
275
+ IKE.bind_header IKE::VendorID, next: IKE::VendorID::PAYLOAD_TYPE
276
+ IKE::Payload.bind_header IKE::VendorID, next: IKE::VendorID::PAYLOAD_TYPE
277
+ IKE::SA.bind_header IKE::VendorID, next: IKE::VendorID::PAYLOAD_TYPE
278
+ IKE::KE.bind_header IKE::VendorID, next: IKE::VendorID::PAYLOAD_TYPE
279
+ IKE::Nonce.bind_header IKE::VendorID, next: IKE::VendorID::PAYLOAD_TYPE
280
+ IKE::Notify.bind_header IKE::VendorID, next: IKE::VendorID::PAYLOAD_TYPE
281
+ IKE::SK.bind_header IKE::VendorID, next: IKE::VendorID::PAYLOAD_TYPE
282
+ IKE::IDi.bind_header IKE::VendorID, next: IKE::VendorID::PAYLOAD_TYPE
283
+ IKE::IDr.bind_header IKE::VendorID, next: IKE::VendorID::PAYLOAD_TYPE
284
+ IKE::Cert.bind_header IKE::VendorID, next: IKE::VendorID::PAYLOAD_TYPE
285
+ IKE::CertReq.bind_header IKE::VendorID, next: IKE::VendorID::PAYLOAD_TYPE
286
+ IKE::Auth.bind_header IKE::VendorID, next: IKE::VendorID::PAYLOAD_TYPE
287
+ IKE::TSi.bind_header IKE::VendorID, next: IKE::VendorID::PAYLOAD_TYPE
288
+ IKE::TSr.bind_header IKE::VendorID, next: IKE::VendorID::PAYLOAD_TYPE
289
+
290
+ # Last defined. To be used as default if no other may be parsed.
291
+ IKE::SA.bind_header IKE::Payload, next: ->(v) { v > 0 }
292
+ IKE::KE.bind_header IKE::Payload, next: ->(v) { v > 0 }
293
+ IKE::Nonce.bind_header IKE::Payload, next: ->(v) { v > 0 }
294
+ IKE::Notify.bind_header IKE::Payload, next: ->(v) { v > 0 }
295
+ IKE::SK.bind_header IKE::Payload, next: ->(v) { v > 0 }
296
+ IKE::IDi.bind_header IKE::Payload, next: ->(v) { v > 0 }
297
+ IKE::IDr.bind_header IKE::Payload, next: ->(v) { v > 0 }
298
+ IKE::Cert.bind_header IKE::Payload, next: ->(v) { v > 0 }
299
+ IKE::CertReq.bind_header IKE::Payload, next: ->(v) { v > 0 }
300
+ IKE::Auth.bind_header IKE::Payload, next: ->(v) { v > 0 }
301
+ IKE::TSi.bind_header IKE::Payload, next: ->(v) { v > 0 }
302
+ IKE::TSr.bind_header IKE::Payload, next: ->(v) { v > 0 }
303
+ IKE::VendorID.bind_header IKE::Payload, next: ->(v) { v > 0 }
304
+ IKE.bind_header IKE::Payload, next: ->(v) { v > 0 }
305
+ IKE::Payload.bind_header IKE::Payload, next: ->(v) { v > 0 }
306
+ end
307
+ end
@@ -0,0 +1,577 @@
1
+ # coding: utf-8
2
+ module PacketGen
3
+ module Header
4
+ class IKE
5
+
6
+ # Transform attribute.
7
+ # 1 2 3
8
+ # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
9
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
10
+ # |A| Attribute Type | AF=0 Attribute Length |
11
+ # |F| | AF=1 Attribute Value |
12
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
13
+ # | AF=0 Attribute Value |
14
+ # | AF=1 Not Transmitted |
15
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16
+ # Such an attribute may have a TLV (Type/length/value) format if AF=0,
17
+ # or a TV format (AF=1).
18
+ # @author Sylvain Daubert
19
+ class Attribute < Types::Fields
20
+
21
+ TYPE_KEY_LENGTH = 14
22
+
23
+ # @!attribute type
24
+ # attribute type
25
+ # @return [Integer]
26
+ define_field :type, Types::Int16
27
+ # @!attribute length
28
+ # attribute length
29
+ # @return [Integer]
30
+ define_field :length, Types::Int16
31
+ # @!attribute value
32
+ # attribute value
33
+ # @return [Integer]
34
+ define_field :value, Types::Int32
35
+
36
+ def initialize(options={})
37
+ super
38
+ if tv_format?
39
+ self[:length].value = (options[:value] & 0xffff)
40
+ else
41
+ self[:length].value = 8 unless options[:length]
42
+ end
43
+ end
44
+
45
+ # @return [Integer]
46
+ def length
47
+ tv_format? ? 4 : self[:length].to_i
48
+ end
49
+
50
+ # @return [Integer]
51
+ def value
52
+ tv_format? ? self[:length].to_i : self[:value].to_i
53
+ end
54
+
55
+ # Populate object from a string
56
+ # @param [String] str
57
+ # @return [self]
58
+ def read(str)
59
+ return self if str.nil?
60
+ force_binary str
61
+ self[:type].read str[0, 2]
62
+ self[:length].read str[2, 2]
63
+ self[:value].read str[4, 4] unless tv_format?
64
+ self
65
+ end
66
+
67
+ # Get binary string
68
+ # @return [String]
69
+ def to_s
70
+ str = self[:type].to_s + self[:length].to_s
71
+ str << self[:value].to_s unless tv_format?
72
+ str
73
+ end
74
+
75
+ # Get a human readable string
76
+ # @return [String]
77
+ def to_human
78
+ name = self.class.constants.grep(/TYPE_/).
79
+ select { |c| self.class.const_get(c) == (type & 0x7fff) }.
80
+ first || "attr[#{type & 0x7fff}]"
81
+ name = name.to_s.sub(/TYPE_/, '')
82
+ "#{name}=#{value}"
83
+ end
84
+
85
+ # Say if attribute use TV format (+true+) or TLV one (+false+)
86
+ # @return [Boolean]
87
+ def tv_format?
88
+ type & 0x8000 == 0x8000
89
+ end
90
+ end
91
+
92
+ # Set of {Attribute} in a {Transform}
93
+ # @author Sylvain Daubert
94
+ class Attributes < Types::Array
95
+ set_of Attribute
96
+ end
97
+
98
+ # SA Tranform substructure, as defined in RFC 7296 §3.3.2
99
+ # 1 2 3
100
+ # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
101
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
102
+ # | Last Substruc | RESERVED | Transform Length |
103
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
104
+ # |Transform Type | RESERVED | Transform ID |
105
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
106
+ # | |
107
+ # ~ Transform Attributes ~
108
+ # | |
109
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
110
+ #
111
+ # == Create a Transform
112
+ # # using type and id names
113
+ # trans = PacketGen::Header::IKE::Transform.new(type: 'ENCR', id: 'AES_CBC')
114
+ # # using integer values
115
+ # trans = PacketGen::Header::IKE::Transform.new(type: 1, id: 12)
116
+ # == Add attributes to a transform
117
+ # # using an Attribute object
118
+ # attr = PacketGen::Header::IKE::Attribute.new(type: 14, value: 128)
119
+ # trans.attributes << attr
120
+ # # using a hash
121
+ # trans.attributes << { type: 14, value: 128 }
122
+ # @author Sylvain Daubert
123
+ class Transform < Types::Fields
124
+
125
+ TYPE_ENCR = 1
126
+ TYPE_PRF = 2
127
+ TYPE_INTG = 3
128
+ TYPE_DH = 4
129
+ TYPE_ESN = 5
130
+
131
+ ENCR_DES_IV64 = 1
132
+ ENCR_DES = 2
133
+ ENCR_3DES = 3
134
+ ENCR_RC5 = 4
135
+ ENCR_IDEA = 5
136
+ ENCR_CAST = 6
137
+ ENCR_BLOWFISH = 7
138
+ ENCR_3IDEA = 8
139
+ ENCR_DES_IV32 = 9
140
+ ENCR_AES_CBC = 12
141
+ ENCR_AES_CTR = 13
142
+ ENCR_AES_CCM8 = 14
143
+ ENCR_AES_CCM12 = 15
144
+ ENCR_AES_CCM16 = 16
145
+ ENCR_AES_GCM8 = 18
146
+ ENCR_AES_GCM12 = 19
147
+ ENCR_AES_GCM16 = 20
148
+ ENCR_CAMELLIA_CBC = 23
149
+ ENCR_CAMELLIA_CTR = 24
150
+ ENCR_CAMELLIA_CCM8 = 25
151
+ ENCR_CAMELLIA_CCM12 = 26
152
+ ENCR_CAMELLIA_CCM16 = 27
153
+ ENCR_CHACHA20_POLY1305 = 28
154
+
155
+ PRF_HMAC_MD5 = 1
156
+ PRF_HMAC_SHA1 = 2
157
+ PRF_AES128_XCBC = 4
158
+ PRF_HMAC_SHA2_256 = 5
159
+ PRF_HMAC_SHA2_384 = 6
160
+ PRF_HMAC_SHA2_512 = 7
161
+ PRF_AES128_CMAC = 8
162
+
163
+ INTG_NONE = 0
164
+ INTG_HMAC_MD5_96 = 1
165
+ INTG_HMAC_SHA1_96 = 2
166
+ INTG_AES_XCBC_96 = 5
167
+ INTG_HMAC_MD5_128 = 6
168
+ INTG_HMAC_SHA1_160 = 7
169
+ INTG_AES_CMAC_96 = 8
170
+ INTG_AES128_GMAC = 9
171
+ INTG_AES192_GMAC = 10
172
+ INTG_AES256_GMAC = 11
173
+ INTG_HMAC_SHA2_256_128 = 12
174
+ INTG_HMAC_SHA2_384_192 = 13
175
+ INTG_HMAC_SHA2_512_256 = 14
176
+
177
+ DH_NONE = 0
178
+ DH_MODP768 = 1
179
+ DH_MODP1024 = 2
180
+ DH_MODP1536 = 5
181
+ DH_MODP2048 = 14
182
+ DH_MODP3072 = 15
183
+ DH_MODP4096 = 16
184
+ DH_MODP6144 = 17
185
+ DH_MODP8192 = 18
186
+ DH_ECP256 = 19
187
+ DH_ECP384 = 20
188
+ DH_ECP521 = 21
189
+ DH_BRAINPOOLP224 = 27
190
+ DH_BRAINPOOLP256 = 28
191
+ DH_BRAINPOOLP384 = 29
192
+ DH_BRAINPOOLP512 = 30
193
+ DH_CURVE25519 = 31
194
+ DH_CURVE448 = 32
195
+
196
+ ESN_NO_ESN = 0
197
+ ESN_ESN = 1
198
+
199
+ # @!attribute last
200
+ # 8-bit last substructure. Specifies whether or not this is the
201
+ # last Transform Substructure in the Proposal. This field has a value of 0
202
+ # if this was the last Transform Substructure, and a value of 3 if
203
+ # there are more Transform Substructures.
204
+ # @return [Integer]
205
+ define_field :last, Types::Int8
206
+ # @!attribute rsv1
207
+ # 8-bit reserved field
208
+ # @return [Integer]
209
+ define_field :rsv1, Types::Int8
210
+ # @!attribute length
211
+ # 16-bit proposal length
212
+ # @return [Integer]
213
+ define_field :length, Types::Int16
214
+ # @!attribute [r] type
215
+ # 8-bit transform type. The Transform Type is the cryptographic
216
+ # algorithm type (i.e. encryption, PRF, integrity, etc.)
217
+ # @return [Integer]
218
+ define_field :type, Types::Int8
219
+ # @!attribute rsv2
220
+ # 8-bit reserved field
221
+ # @return [Integer]
222
+ define_field :rsv2, Types::Int8
223
+ # @!attribute [r] id
224
+ # 16-bit transform ID. The Transform ID is the specific instance of
225
+ # the proposed transform type.
226
+ # @return [Integer]
227
+ define_field :id, Types::Int16
228
+ # @!attribute attributes
229
+ # Set of attributes for this transform
230
+ # @return [Attributes]
231
+ define_field :attributes, Attributes
232
+
233
+ def initialize(options={})
234
+ super
235
+ self[:length].value = sz unless options[:length]
236
+ self.type = options[:type] if options[:type]
237
+ self.id = options[:id] if options[:id]
238
+ end
239
+
240
+ # Set transform type
241
+ # @param [Integer,String] value
242
+ # @return [Integer]
243
+ def type=(value)
244
+ type = case value
245
+ when Integer
246
+ value
247
+ else
248
+ c = self.class.constants.grep(/TYPE_#{value}/).first
249
+ c ? self.class.const_get(c) : nil
250
+ end
251
+ raise ArgumentError, "unknown type #{value.inspect}" unless type
252
+ self[:type].value = type
253
+ end
254
+
255
+ # Set transform ID
256
+ # @param [Integer,String] value
257
+ # @return [Integer]
258
+ def id=(value)
259
+ id = case value
260
+ when Integer
261
+ value
262
+ else
263
+ c = self.class.constants.grep(/#{human_type}_#{value}/).first
264
+ c ? self.class.const_get(c) : nil
265
+ end
266
+ raise ArgumentError, "unknown ID #{value.inspect}" unless id
267
+ self[:id].value = id
268
+ end
269
+
270
+ # Populate object from a string
271
+ # @param [String] str
272
+ # @return [self]
273
+ def read(str)
274
+ super
275
+ hlen = self.class.new.sz
276
+ attr_len = length - hlen
277
+ attributes.read(str[hlen, attr_len])
278
+ self
279
+ end
280
+
281
+ # Compute length and set {#length} field
282
+ # @return [Integer] new length
283
+ def calc_length
284
+ self[:length].value = sz
285
+ end
286
+
287
+ # Get a human readable string
288
+ # @return [String]
289
+ def to_human
290
+ h = "#{human_type}(#{human_id}"
291
+ h << ",#{attributes.to_human}" if attributes.size > 0
292
+ h << ')'
293
+ end
294
+
295
+ # Get human-readable type
296
+ # @return [String]
297
+ def human_type
298
+ name = self.class.constants.grep(/TYPE/).
299
+ select { |c| self.class.const_get(c) == type }.
300
+ first || "type[#{type}]"
301
+ name.to_s.sub(/TYPE_/, '')
302
+ end
303
+
304
+ # Get human-readable ID
305
+ # @return [String]
306
+ def human_id
307
+ name = self.class.constants.grep(/#{human_type}_/).
308
+ select { |c| self.class.const_get(c) == id }.
309
+ first || "ID=#{id}"
310
+ name.to_s.sub(/#{human_type}_/, '')
311
+ end
312
+
313
+ # Say if this transform is the last one (from {#last} field)
314
+ # @return [Boolean,nil] returns a Boolean when {#last} has defined value (+0+ => +true+, +3+ => +false+), else +nil+ is returned.
315
+ def last?
316
+ case last
317
+ when 0
318
+ true
319
+ when 3
320
+ false
321
+ else
322
+ nil
323
+ end
324
+ end
325
+ end
326
+
327
+ # Set of {Transform} in a {SAProposal}
328
+ # @author Sylvain Daubert
329
+ class Transforms < Types::Array
330
+ set_of Transform
331
+
332
+ # Same as {Types::Array#push} but update previous {Transform#last} attribute
333
+ # @see Types::Array#push
334
+ def push(trans)
335
+ super
336
+ self[-2].last = 3 if size > 1
337
+ self[-1].last = 0
338
+ self
339
+ end
340
+ end
341
+
342
+ # SA Proposal, as defined in RFC 7296 §3.3.1
343
+ # 1 2 3
344
+ # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
345
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
346
+ # | Last Substruc | RESERVED | Proposal Length |
347
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
348
+ # | Proposal Num | Protocol ID | SPI Size |Num Transforms|
349
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
350
+ # ~ SPI (variable) ~
351
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
352
+ # | |
353
+ # ~ <Transforms> ~
354
+ # | |
355
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
356
+ #
357
+ # == Create a proposal
358
+ # # using protocol name
359
+ # proposal = PacketGen::Header::IKE::Proposal.new(num: 1, protocol: 'IKE')
360
+ # # using integer values
361
+ # proposal = PacketGen::Header::IKE::Proposal.new(num: 1, protocol: 1)
362
+ # == Add transforms to a proposal
363
+ # # using a Transform object
364
+ # trans = PacketGen::Header::IKE::Transform.new(type: 'ENCR', id: '3DES')
365
+ # proposal.transforms << trans
366
+ # # using a hash
367
+ # proposal.transforms << { type: 'ENCR', id: '3DES' }
368
+ # @author Sylvain Daubert
369
+ class SAProposal < Types::Fields
370
+
371
+ # @!attribute last
372
+ # 8-bit last substructure. Specifies whether or not this is the
373
+ # last Proposal Substructure in the SA. This field has a value of 0
374
+ # if this was the last Proposal Substructure, and a value of 2 if
375
+ # there are more Proposal Substructures.
376
+ # @return [Integer]
377
+ define_field :last, Types::Int8
378
+ # @!attribute reserved
379
+ # 8-bit reserved field
380
+ # @return [Integer]
381
+ define_field :reserved, Types::Int8
382
+ # @!attribute length
383
+ # 16-bit proposal length
384
+ # @return [Integer]
385
+ define_field :length, Types::Int16
386
+ # @!attribute num
387
+ # 8-bit proposal number. When a proposal is made, the first
388
+ # proposal in an SA payload MUST be 1, and subsequent proposals MUST
389
+ # be one more than the previous proposal (indicating an OR of the
390
+ # two proposals). When a proposal is accepted, the proposal number
391
+ # in the SA payload MUST match the number on the proposal sent that
392
+ # was accepted.
393
+ # @return [Integer]
394
+ define_field :num, Types::Int8, default: 1
395
+ # @!attribute [r] protocol
396
+ # 8-bit protocol ID. Specify IPsec protocol currently negociated.
397
+ # May 1 (IKE), 2 (AH) or 3 (ESP).
398
+ # @return [Integer]
399
+ define_field :protocol, Types::Int8
400
+ # @!attribute spi_size
401
+ # 8-bit SPI size. Give size of SPI field. Set to 0 for an initial IKE SA
402
+ # negotiation, as SPI is obtained from outer header.
403
+ # @return [Integer]
404
+ define_field :spi_size, Types::Int8, default: 0
405
+ # @!attribute num_trans
406
+ # 8-bit number of transformations
407
+ # @return [Integer]
408
+ define_field :num_trans, Types::Int8, default: 0
409
+ # @!attribute spi
410
+ # the sending entity's SPI. When the {#spi_size} field is zero,
411
+ # this field is not present in the proposal.
412
+ # @return [String]
413
+ define_field :spi, Types::String, builder: ->(t) { Types::String.new('', length_from: t[:spi_size]) }
414
+ # @!attribute transforms
415
+ # 8-bit set of tranforms for this proposal
416
+ # @return [Transforms]
417
+ define_field :transforms, Transforms, builder: ->(t) { Transforms.new(counter: t[:num_trans]) }
418
+
419
+ def initialize(options={})
420
+ if options[:spi] and options[:spi_size].nil?
421
+ options[:spi_size] = options[:spi].size
422
+ end
423
+ super
424
+ self[:length].value = sz unless options[:length]
425
+ self.protocol = options[:protocol] if options[:protocol]
426
+ end
427
+
428
+ # Set protocol
429
+ # @param [Integer,String] value
430
+ # @return [Integer]
431
+ def protocol=(value)
432
+ proto = case value
433
+ when Integer
434
+ value
435
+ else
436
+ c = IKE.constants.grep(/PROTO_#{value}/).first
437
+ c ? IKE.const_get(c) : nil
438
+ end
439
+ raise ArgumentError, "unknown protocol #{value.inspect}" unless proto
440
+ self[:protocol].value = proto
441
+ end
442
+
443
+ # Populate object from a string
444
+ # @param [String] str
445
+ # @return [self]
446
+ def read(str)
447
+ super
448
+ hlen = self.class.new.sz + spi_size
449
+ tlen = length - hlen
450
+ transforms.read(str[hlen, tlen])
451
+ self
452
+ end
453
+
454
+ # Compute length and set {#length} field
455
+ # @return [Integer] new length
456
+ def calc_length
457
+ transforms.each { |t| t.calc_length }
458
+ self[:length].value = sz
459
+ end
460
+
461
+ # Get a human readable string
462
+ # @return [String]
463
+ def to_human
464
+ str = "##{num} #{human_protocol}"
465
+ case spi_size
466
+ when 4
467
+ str << "(spi:0x%08x)" % Types::Int32.new.read(spi).to_i
468
+ when 8
469
+ str << "(spi:0x%016x)" % Types::Int64.new.read(spi).to_i
470
+ end
471
+ str << ":#{transforms.to_human}"
472
+ end
473
+
474
+ # Get protocol name
475
+ # @return [String]
476
+ def human_protocol
477
+ name = IKE.constants.grep(/PROTO/).
478
+ select { |c| IKE.const_get(c) == protocol }.
479
+ first || "proto #{protocol}"
480
+ name.to_s.sub(/PROTO_/, '')
481
+ end
482
+
483
+ # Say if this proposal is the last one (from {#last} field)
484
+ # @return [Boolean,nil] returns a Boolean when {#last} has defined value
485
+ # (+0+ => +true+, +2+ => +false+), else +nil+ is returned.
486
+ def last?
487
+ case last
488
+ when 0
489
+ true
490
+ when 2
491
+ false
492
+ else
493
+ nil
494
+ end
495
+ end
496
+ end
497
+
498
+ # Set of {SAProposal}
499
+ # @author Sylvain Daubert
500
+ class SAProposals < Types::Array
501
+ set_of SAProposal
502
+
503
+ # Separator used between proposals in {#to_human}
504
+ HUMAN_SEPARATOR = '; '
505
+
506
+ # Same as {Types::Array#push} but update previous {SAProposal#last} attribute
507
+ # @see Types::Array#push
508
+ def push(prop)
509
+ super
510
+ self[-2].last = 2 if size > 1
511
+ self[-1].last = 0
512
+ self
513
+ end
514
+ end
515
+
516
+ # This class handles Security Assocation payloads, as defined in RFC 7296 §3.3.
517
+ #
518
+ # A SA payload contains a generic payload header (see {Payload}) and a set of
519
+ # {SAProposal} ({#proposals} field, which is a {SAProposals} object):
520
+ # 1 2 3
521
+ # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
522
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
523
+ # | Next Payload |C| RESERVED | Payload Length |
524
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
525
+ # | |
526
+ # ~ <Proposals> ~
527
+ # | |
528
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
529
+ #
530
+ # == Create a SA payload
531
+ # # Create a IKE packet with a SA payload
532
+ # pkt = PacketGen.gen('IP').add('UDP').add('IKE').add('IKE::SA')
533
+ # # add a proposal. Protocol name is taken from SAProposal::PROTO_* constants
534
+ # pkt.ike_sa.proposals << { num: 1, protocol: 'ESP' }
535
+ # # add a transform to this proposal.
536
+ # # type name is taken from Transform::TYPE_* constants.
537
+ # # ID is taken from Transform::<TYPE>_* constants.
538
+ # pkt.ike_sa.proposals.first.transforms << { type: 'ENCR', id: 'AES_CTR' }
539
+ # # and finally, add an attribute to this transform (here, KEY_SIZE = 128 bits)
540
+ # pkt.ike_sa.proposals[0].transforms[0].attributes << { type: 0x800e, value: 128 }
541
+ # pkt.calc_length
542
+ # @author Sylvain Daubert
543
+ class SA < Payload
544
+
545
+ # Payload type number
546
+ PAYLOAD_TYPE = 33
547
+
548
+ delete_field :content
549
+ # @!attribute proposals
550
+ # Set of SA proposals
551
+ # @return [SAProposals]
552
+ define_field_before :body, :proposals, SAProposals
553
+
554
+ # Populate object from a string
555
+ # @param [String] str
556
+ # @return [self]
557
+ def read(str)
558
+ super
559
+ hlen = self.class.new.sz
560
+ plen = length - hlen
561
+ proposals.read str[hlen, plen]
562
+ body.read str[hlen+plen..-1]
563
+ self
564
+ end
565
+
566
+ # Compute length and set {#length} field
567
+ # @return [Integer] new length
568
+ def calc_length
569
+ proposals.each { |p| p.calc_length }
570
+ super
571
+ end
572
+ end
573
+ end
574
+
575
+ self.add_class IKE::SA
576
+ end
577
+ end