packetgen 1.4.3 → 2.0.0

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