]>
Commit | Line | Data |
---|---|---|
da42afc5 JH |
1 | /** |
2 | * @file proposal_substructure.h | |
3 | * | |
4 | * @brief Declaration of the class proposal_substructure_t. | |
5 | * | |
6 | * An object of this type represents an IKEv2 PROPOSAL Substructure and contains transforms. | |
7 | * | |
8 | */ | |
9 | ||
10 | /* | |
11 | * Copyright (C) 2005 Jan Hutter, Martin Willi | |
12 | * Hochschule fuer Technik Rapperswil | |
13 | * | |
14 | * This program is free software; you can redistribute it and/or modify it | |
15 | * under the terms of the GNU General Public License as published by the | |
16 | * Free Software Foundation; either version 2 of the License, or (at your | |
17 | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. | |
18 | * | |
19 | * This program is distributed in the hope that it will be useful, but | |
20 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
21 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
22 | * for more details. | |
23 | */ | |
b860cffd | 24 | |
da42afc5 JH |
25 | /* offsetof macro */ |
26 | #include <stddef.h> | |
27 | ||
28 | #include "proposal_substructure.h" | |
29 | ||
30 | #include "encodings.h" | |
b860cffd | 31 | #include "transform_substructure.h" |
da42afc5 JH |
32 | #include "../types.h" |
33 | #include "../utils/allocator.h" | |
34 | #include "../utils/linked_list.h" | |
35 | ||
36 | /** | |
37 | * Private data of an proposal_substructure_t' Object | |
38 | * | |
39 | */ | |
40 | typedef struct private_proposal_substructure_s private_proposal_substructure_t; | |
41 | ||
42 | struct private_proposal_substructure_s { | |
43 | /** | |
44 | * public proposal_substructure_t interface | |
45 | */ | |
46 | proposal_substructure_t public; | |
47 | ||
48 | /** | |
49 | * next payload type | |
50 | */ | |
51 | u_int8_t next_payload; | |
52 | ||
53 | ||
54 | /** | |
55 | * Length of this payload | |
56 | */ | |
57 | u_int16_t proposal_length; | |
58 | ||
59 | ||
60 | /** | |
61 | * Proposal number | |
62 | */ | |
63 | u_int8_t proposal_number; | |
64 | ||
65 | /** | |
66 | * Protocol ID | |
67 | */ | |
68 | u_int8_t protocol_id; | |
69 | ||
70 | /** | |
71 | * SPI size of the following SPI | |
72 | */ | |
73 | u_int8_t spi_size; | |
74 | ||
75 | /** | |
76 | * Number of transforms | |
77 | */ | |
78 | u_int8_t transforms_count; | |
79 | ||
80 | /** | |
81 | * SPI is stored as chunk | |
82 | */ | |
83 | chunk_t spi; | |
84 | ||
85 | /** | |
86 | * Transforms are stored in a linked_list_t | |
87 | */ | |
88 | linked_list_t * transforms; | |
67978e0b JH |
89 | |
90 | /** | |
91 | * @brief Computes the length of this substructure. | |
92 | * | |
93 | * @param this calling private_proposal_substructure_t object | |
94 | * @return | |
95 | * SUCCESS in any case | |
96 | */ | |
97 | status_t (*compute_length) (private_proposal_substructure_t *this); | |
da42afc5 JH |
98 | }; |
99 | ||
100 | /** | |
101 | * Encoding rules to parse or generate a Proposal substructure | |
102 | * | |
103 | * The defined offsets are the positions in a object of type | |
104 | * private_proposal_substructure_t. | |
105 | * | |
106 | */ | |
107 | encoding_rule_t proposal_substructure_encodings[] = { | |
108 | /* 1 Byte next payload type, stored in the field next_payload */ | |
109 | { U_INT_8, offsetof(private_proposal_substructure_t, next_payload) }, | |
110 | /* Reserved Byte is skipped */ | |
111 | { RESERVED_BYTE, 0 }, | |
b860cffd | 112 | /* Length of the whole proposal substructure payload*/ |
da42afc5 JH |
113 | { PAYLOAD_LENGTH, offsetof(private_proposal_substructure_t, proposal_length) }, |
114 | /* proposal number is a number of 8 bit */ | |
115 | { U_INT_8, offsetof(private_proposal_substructure_t, proposal_number) }, | |
116 | /* protocol ID is a number of 8 bit */ | |
117 | { U_INT_8, offsetof(private_proposal_substructure_t, protocol_id) }, | |
118 | /* SPI Size has its own type */ | |
119 | { SPI_SIZE, offsetof(private_proposal_substructure_t, spi_size) }, | |
120 | /* Number of transforms is a number of 8 bit */ | |
121 | { U_INT_8, offsetof(private_proposal_substructure_t, transforms_count) }, | |
122 | /* SPI is a chunk of variable size*/ | |
123 | { SPI, offsetof(private_proposal_substructure_t, spi) }, | |
124 | /* Transforms are stored in a transform substructure, | |
125 | offset points to a linked_list_t pointer */ | |
126 | { TRANSFORMS, offsetof(private_proposal_substructure_t, transforms) } | |
127 | }; | |
128 | ||
e31eb71e JH |
129 | /* |
130 | 1 2 3 | |
131 | 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 | |
132 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
133 | ! 0 (last) or 2 ! RESERVED ! Proposal Length ! | |
134 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
135 | ! Proposal # ! Protocol ID ! SPI Size !# of Transforms! | |
136 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
137 | ~ SPI (variable) ~ | |
138 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
139 | ! ! | |
140 | ~ <Transforms> ~ | |
141 | ! ! | |
142 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
143 | */ | |
144 | ||
145 | /** | |
146 | * Implements payload_t's verify function. | |
147 | * See #payload_s.verify for description. | |
148 | */ | |
149 | static status_t verify(private_proposal_substructure_t *this) | |
150 | { | |
151 | if ((this->next_payload != NO_PAYLOAD) && (this->next_payload != PROPOSAL_SUBSTRUCTURE)) | |
152 | { | |
153 | /* must be 0 or 2 */ | |
154 | return FAILED; | |
155 | } | |
156 | if (this->transforms_count != this->transforms->get_count(this->transforms)) | |
157 | { | |
158 | /* must be the same! */ | |
159 | return FAILED; | |
160 | } | |
161 | ||
162 | if (this->protocol_id > 4) | |
163 | { | |
164 | /* reserved are not supported */ | |
165 | return FAILED; | |
166 | } | |
167 | ||
168 | /* proposal number is checked in SA payload */ | |
169 | return SUCCESS; | |
170 | } | |
171 | ||
da42afc5 JH |
172 | /** |
173 | * Implements payload_t's and proposal_substructure_t's destroy function. | |
174 | * See #payload_s.destroy or proposal_substructure_s.destroy for description. | |
175 | */ | |
176 | static status_t destroy(private_proposal_substructure_t *this) | |
177 | { | |
178 | /* all proposals are getting destroyed */ | |
179 | while (this->transforms->get_count(this->transforms) > 0) | |
180 | { | |
b860cffd | 181 | transform_substructure_t *current_transform; |
da42afc5 JH |
182 | if (this->transforms->remove_last(this->transforms,(void **)¤t_transform) != SUCCESS) |
183 | { | |
184 | break; | |
185 | } | |
186 | current_transform->destroy(current_transform); | |
187 | } | |
188 | this->transforms->destroy(this->transforms); | |
189 | ||
190 | if (this->spi.ptr != NULL) | |
191 | { | |
192 | allocator_free(this->spi.ptr); | |
193 | } | |
194 | ||
195 | allocator_free(this); | |
196 | ||
197 | return SUCCESS; | |
198 | } | |
199 | ||
200 | /** | |
201 | * Implements payload_t's get_encoding_rules function. | |
202 | * See #payload_s.get_encoding_rules for description. | |
203 | */ | |
204 | static status_t get_encoding_rules(private_proposal_substructure_t *this, encoding_rule_t **rules, size_t *rule_count) | |
205 | { | |
206 | *rules = proposal_substructure_encodings; | |
207 | *rule_count = sizeof(proposal_substructure_encodings) / sizeof(encoding_rule_t); | |
208 | ||
209 | return SUCCESS; | |
210 | } | |
211 | ||
212 | /** | |
213 | * Implements payload_t's get_type function. | |
214 | * See #payload_s.get_type for description. | |
215 | */ | |
216 | static payload_type_t get_type(private_proposal_substructure_t *this) | |
217 | { | |
218 | return PROPOSAL_SUBSTRUCTURE; | |
219 | } | |
220 | ||
221 | /** | |
222 | * Implements payload_t's get_next_type function. | |
223 | * See #payload_s.get_next_type for description. | |
224 | */ | |
225 | static payload_type_t get_next_type(private_proposal_substructure_t *this) | |
226 | { | |
227 | return (this->next_payload); | |
228 | } | |
229 | ||
32cbc7bc JH |
230 | /** |
231 | * Implements payload_t's set_next_type function. | |
232 | * See #payload_s.set_next_type for description. | |
233 | */ | |
234 | static status_t set_next_type(private_proposal_substructure_t *this,payload_type_t type) | |
235 | { | |
236 | return SUCCESS; | |
237 | } | |
238 | ||
da42afc5 JH |
239 | /** |
240 | * Implements payload_t's get_length function. | |
241 | * See #payload_s.get_length for description. | |
242 | */ | |
243 | static size_t get_length(private_proposal_substructure_t *this) | |
244 | { | |
245 | return this->proposal_length; | |
246 | } | |
247 | ||
b860cffd JH |
248 | /** |
249 | * Implements proposal_substructure_t's create_transform_substructure_iterator function. | |
250 | * See #proposal_substructure_s.create_transform_substructure_iterator for description. | |
251 | */ | |
252 | static status_t create_transform_substructure_iterator (private_proposal_substructure_t *this,linked_list_iterator_t **iterator,bool forward) | |
253 | { | |
254 | return (this->transforms->create_iterator(this->transforms,iterator,forward)); | |
255 | } | |
256 | ||
257 | /** | |
258 | * Implements proposal_substructure_t's add_transform_substructure function. | |
259 | * See #proposal_substructure_s.add_transform_substructure for description. | |
260 | */ | |
261 | static status_t add_transform_substructure (private_proposal_substructure_t *this,transform_substructure_t *transform) | |
262 | { | |
a14dffd1 JH |
263 | status_t status; |
264 | if (this->transforms->get_count(this->transforms) > 0) | |
265 | { | |
266 | transform_substructure_t *last_transform; | |
267 | status = this->transforms->get_last(this->transforms,(void **) &last_transform); | |
268 | /* last transform is now not anymore last one */ | |
269 | last_transform->set_is_last_transform(last_transform,FALSE); | |
270 | ||
271 | } | |
272 | transform->set_is_last_transform(transform,TRUE); | |
273 | ||
274 | status = this->transforms->insert_last(this->transforms,(void *) transform); | |
67978e0b | 275 | this->compute_length(this); |
a14dffd1 | 276 | return status; |
67978e0b JH |
277 | } |
278 | ||
279 | /** | |
280 | * Implements proposal_substructure_t's set_proposal_number function. | |
281 | * See #proposal_substructure_s.set_proposal_number for description. | |
282 | */ | |
283 | static status_t set_proposal_number(private_proposal_substructure_t *this,u_int8_t proposal_number) | |
284 | { | |
285 | this->proposal_number = proposal_number; | |
286 | return SUCCESS; | |
287 | } | |
288 | ||
289 | /** | |
290 | * Implements proposal_substructure_t's get_proposal_number function. | |
291 | * See #proposal_substructure_s.get_proposal_number for description. | |
292 | */ | |
293 | static u_int8_t get_proposal_number (private_proposal_substructure_t *this) | |
294 | { | |
295 | return (this->proposal_number); | |
296 | } | |
297 | ||
298 | /** | |
299 | * Implements proposal_substructure_t's set_protocol_id function. | |
300 | * See #proposal_substructure_s.set_protocol_id for description. | |
301 | */ | |
302 | static status_t set_protocol_id(private_proposal_substructure_t *this,u_int8_t protocol_id) | |
303 | { | |
304 | this->protocol_id = protocol_id; | |
305 | return SUCCESS; | |
306 | } | |
307 | ||
308 | /** | |
309 | * Implements proposal_substructure_t's get_protocol_id function. | |
310 | * See #proposal_substructure_s.get_protocol_id for description. | |
311 | */ | |
312 | static u_int8_t get_protocol_id (private_proposal_substructure_t *this) | |
313 | { | |
314 | return (this->protocol_id); | |
b860cffd JH |
315 | } |
316 | ||
67978e0b JH |
317 | |
318 | /** | |
319 | * Implements proposal_substructure_t's set_spi function. | |
320 | * See #proposal_substructure_s.set_spi for description. | |
321 | */ | |
322 | static status_t set_spi (private_proposal_substructure_t *this, chunk_t spi) | |
323 | { | |
324 | /* first delete already set spi value */ | |
325 | if (this->spi.ptr != NULL) | |
326 | { | |
327 | allocator_free(this->spi.ptr); | |
328 | this->spi.ptr = NULL; | |
329 | this->spi.len = 0; | |
330 | this->compute_length(this); | |
331 | } | |
332 | ||
333 | this->spi.ptr = allocator_clone_bytes(spi.ptr,spi.len); | |
334 | if (this->spi.ptr == NULL) | |
335 | { | |
336 | return OUT_OF_RES; | |
337 | } | |
338 | this->spi.len = spi.len; | |
339 | this->spi_size = spi.len; | |
340 | this->compute_length(this); | |
341 | ||
342 | return SUCCESS; | |
343 | } | |
344 | ||
345 | /** | |
346 | * Implements proposal_substructure_t's get_spi function. | |
347 | * See #proposal_substructure_s.get_spi for description. | |
348 | */ | |
349 | static chunk_t get_spi (private_proposal_substructure_t *this) | |
350 | { | |
351 | chunk_t spi; | |
352 | spi.ptr = this->spi.ptr; | |
353 | spi.len = this->spi.len; | |
354 | ||
355 | return spi; | |
356 | } | |
357 | ||
358 | /** | |
359 | * Implements private_proposal_substructure_t's compute_length function. | |
360 | * See #private_proposal_substructure_s.compute_length for description. | |
361 | */ | |
362 | static status_t compute_length (private_proposal_substructure_t *this) | |
363 | { | |
364 | linked_list_iterator_t *iterator; | |
365 | status_t status; | |
366 | size_t transforms_count = 0; | |
367 | size_t length = PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH; | |
368 | status = this->transforms->create_iterator(this->transforms,&iterator,TRUE); | |
369 | if (status != SUCCESS) | |
370 | { | |
371 | return length; | |
372 | } | |
373 | while (iterator->has_next(iterator)) | |
374 | { | |
375 | payload_t * current_transform; | |
376 | iterator->current(iterator,(void **) ¤t_transform); | |
377 | length += current_transform->get_length(current_transform); | |
378 | transforms_count++; | |
379 | } | |
a14dffd1 | 380 | iterator->destroy(iterator); |
67978e0b JH |
381 | |
382 | length += this->spi.len; | |
67978e0b JH |
383 | this->transforms_count= transforms_count; |
384 | this->proposal_length = length; | |
385 | ||
386 | return SUCCESS; | |
387 | } | |
388 | ||
389 | ||
da42afc5 JH |
390 | /* |
391 | * Described in header | |
392 | */ | |
393 | proposal_substructure_t *proposal_substructure_create() | |
394 | { | |
395 | private_proposal_substructure_t *this = allocator_alloc_thing(private_proposal_substructure_t); | |
396 | if (this == NULL) | |
397 | { | |
398 | return NULL; | |
399 | } | |
e31eb71e JH |
400 | |
401 | /* interface functions */ | |
402 | this->public.payload_interface.verify = (status_t (*) (payload_t *))verify; | |
da42afc5 JH |
403 | this->public.payload_interface.get_encoding_rules = (status_t (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules; |
404 | this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length; | |
405 | this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type; | |
32cbc7bc | 406 | this->public.payload_interface.set_next_type = (status_t (*) (payload_t *,payload_type_t)) set_next_type; |
da42afc5 JH |
407 | this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type; |
408 | this->public.payload_interface.destroy = (status_t (*) (payload_t *))destroy; | |
e31eb71e JH |
409 | |
410 | /* public functions */ | |
b860cffd JH |
411 | this->public.create_transform_substructure_iterator = (status_t (*) (proposal_substructure_t *,linked_list_iterator_t **,bool)) create_transform_substructure_iterator; |
412 | this->public.add_transform_substructure = (status_t (*) (proposal_substructure_t *,transform_substructure_t *)) add_transform_substructure; | |
67978e0b JH |
413 | this->public.set_proposal_number = (status_t (*) (proposal_substructure_t *,u_int8_t))set_proposal_number; |
414 | this->public.get_proposal_number = (u_int8_t (*) (proposal_substructure_t *)) get_proposal_number; | |
415 | this->public.set_protocol_id = (status_t (*) (proposal_substructure_t *,u_int8_t))set_protocol_id; | |
416 | this->public.get_protocol_id = (u_int8_t (*) (proposal_substructure_t *)) get_protocol_id; | |
417 | this->public.set_spi = (status_t (*) (proposal_substructure_t *,chunk_t))set_spi; | |
418 | this->public.get_spi = (chunk_t (*) (proposal_substructure_t *)) get_spi; | |
da42afc5 JH |
419 | this->public.destroy = (status_t (*) (proposal_substructure_t *)) destroy; |
420 | ||
67978e0b JH |
421 | /* private functions */ |
422 | this->compute_length = compute_length; | |
423 | ||
da42afc5 JH |
424 | /* set default values of the fields */ |
425 | this->next_payload = NO_PAYLOAD; | |
426 | this->proposal_length = 0; | |
427 | this->proposal_number = 0; | |
428 | this->protocol_id = 0; | |
429 | this->transforms_count = 0; | |
430 | this->spi_size = 0; | |
431 | this->spi.ptr = NULL; | |
432 | this->spi.len = 0; | |
433 | ||
434 | this->transforms = linked_list_create(); | |
435 | ||
436 | if (this->transforms == NULL) | |
437 | { | |
438 | allocator_free(this); | |
439 | return NULL; | |
440 | } | |
441 | return (&(this->public)); | |
442 | } |