2 * @file proposal_substructure.h
4 * @brief Declaration of the class proposal_substructure_t.
6 * An object of this type represents an IKEv2 PROPOSAL Substructure and contains transforms.
11 * Copyright (C) 2005 Jan Hutter, Martin Willi
12 * Hochschule fuer Technik Rapperswil
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>.
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
28 #include "proposal_substructure.h"
30 #include <encoding/payloads/encodings.h>
31 #include <encoding/payloads/transform_substructure.h>
33 #include <utils/allocator.h>
34 #include <utils/linked_list.h>
37 * Private data of an proposal_substructure_t' Object
40 typedef struct private_proposal_substructure_s private_proposal_substructure_t
;
42 struct private_proposal_substructure_s
{
44 * public proposal_substructure_t interface
46 proposal_substructure_t
public;
51 u_int8_t next_payload
;
55 * Length of this payload
57 u_int16_t proposal_length
;
63 u_int8_t proposal_number
;
71 * SPI size of the following SPI
76 * Number of transforms
78 u_int8_t transforms_count
;
81 * SPI is stored as chunk
86 * Transforms are stored in a linked_list_t
88 linked_list_t
* transforms
;
91 * @brief Computes the length of this substructure.
93 * @param this calling private_proposal_substructure_t object
97 status_t (*compute_length
) (private_proposal_substructure_t
*this);
101 * Encoding rules to parse or generate a Proposal substructure
103 * The defined offsets are the positions in a object of type
104 * private_proposal_substructure_t.
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 },
112 /* Length of the whole proposal substructure payload*/
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
) }
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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
138 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
142 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
146 * Implements payload_t's verify function.
147 * See #payload_s.verify for description.
149 static status_t
verify(private_proposal_substructure_t
*this)
151 if ((this->next_payload
!= NO_PAYLOAD
) && (this->next_payload
!= PROPOSAL_SUBSTRUCTURE
))
156 if (this->transforms_count
!= this->transforms
->get_count(this->transforms
))
158 /* must be the same! */
162 if (this->protocol_id
> 4)
164 /* reserved are not supported */
168 /* proposal number is checked in SA payload */
173 * Implements payload_t's get_encoding_rules function.
174 * See #payload_s.get_encoding_rules for description.
176 static status_t
get_encoding_rules(private_proposal_substructure_t
*this, encoding_rule_t
**rules
, size_t *rule_count
)
178 *rules
= proposal_substructure_encodings
;
179 *rule_count
= sizeof(proposal_substructure_encodings
) / sizeof(encoding_rule_t
);
185 * Implements payload_t's get_type function.
186 * See #payload_s.get_type for description.
188 static payload_type_t
get_type(private_proposal_substructure_t
*this)
190 return PROPOSAL_SUBSTRUCTURE
;
194 * Implements payload_t's get_next_type function.
195 * See #payload_s.get_next_type for description.
197 static payload_type_t
get_next_type(private_proposal_substructure_t
*this)
199 return (this->next_payload
);
203 * Implements payload_t's set_next_type function.
204 * See #payload_s.set_next_type for description.
206 static status_t
set_next_type(private_proposal_substructure_t
*this,payload_type_t type
)
212 * Implements payload_t's get_length function.
213 * See #payload_s.get_length for description.
215 static size_t get_length(private_proposal_substructure_t
*this)
217 return this->proposal_length
;
221 * Implements proposal_substructure_t's create_transform_substructure_iterator function.
222 * See #proposal_substructure_s.create_transform_substructure_iterator for description.
224 static status_t
create_transform_substructure_iterator (private_proposal_substructure_t
*this,linked_list_iterator_t
**iterator
,bool forward
)
226 return (this->transforms
->create_iterator(this->transforms
,iterator
,forward
));
230 * Implements proposal_substructure_t's add_transform_substructure function.
231 * See #proposal_substructure_s.add_transform_substructure for description.
233 static status_t
add_transform_substructure (private_proposal_substructure_t
*this,transform_substructure_t
*transform
)
236 if (this->transforms
->get_count(this->transforms
) > 0)
238 transform_substructure_t
*last_transform
;
239 status
= this->transforms
->get_last(this->transforms
,(void **) &last_transform
);
240 /* last transform is now not anymore last one */
241 last_transform
->set_is_last_transform(last_transform
,FALSE
);
244 transform
->set_is_last_transform(transform
,TRUE
);
246 status
= this->transforms
->insert_last(this->transforms
,(void *) transform
);
247 this->compute_length(this);
252 * Implements proposal_substructure_t's set_proposal_number function.
253 * See #proposal_substructure_s.set_proposal_number for description.
255 static status_t
set_proposal_number(private_proposal_substructure_t
*this,u_int8_t proposal_number
)
257 this->proposal_number
= proposal_number
;
262 * Implements proposal_substructure_t's get_proposal_number function.
263 * See #proposal_substructure_s.get_proposal_number for description.
265 static u_int8_t
get_proposal_number (private_proposal_substructure_t
*this)
267 return (this->proposal_number
);
271 * Implements proposal_substructure_t's set_protocol_id function.
272 * See #proposal_substructure_s.set_protocol_id for description.
274 static status_t
set_protocol_id(private_proposal_substructure_t
*this,u_int8_t protocol_id
)
276 this->protocol_id
= protocol_id
;
281 * Implements proposal_substructure_t's get_protocol_id function.
282 * See #proposal_substructure_s.get_protocol_id for description.
284 static u_int8_t
get_protocol_id (private_proposal_substructure_t
*this)
286 return (this->protocol_id
);
291 * Implements proposal_substructure_t's set_spi function.
292 * See #proposal_substructure_s.set_spi for description.
294 static status_t
set_spi (private_proposal_substructure_t
*this, chunk_t spi
)
296 /* first delete already set spi value */
297 if (this->spi
.ptr
!= NULL
)
299 allocator_free(this->spi
.ptr
);
300 this->spi
.ptr
= NULL
;
302 this->compute_length(this);
305 this->spi
.ptr
= allocator_clone_bytes(spi
.ptr
,spi
.len
);
306 if (this->spi
.ptr
== NULL
)
310 this->spi
.len
= spi
.len
;
311 this->spi_size
= spi
.len
;
312 this->compute_length(this);
318 * Implements proposal_substructure_t's get_spi function.
319 * See #proposal_substructure_s.get_spi for description.
321 static chunk_t
get_spi (private_proposal_substructure_t
*this)
324 spi
.ptr
= this->spi
.ptr
;
325 spi
.len
= this->spi
.len
;
331 * Implements private_proposal_substructure_t's compute_length function.
332 * See #private_proposal_substructure_s.compute_length for description.
334 static status_t
compute_length (private_proposal_substructure_t
*this)
336 linked_list_iterator_t
*iterator
;
338 size_t transforms_count
= 0;
339 size_t length
= PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH
;
340 status
= this->transforms
->create_iterator(this->transforms
,&iterator
,TRUE
);
341 if (status
!= SUCCESS
)
345 while (iterator
->has_next(iterator
))
347 payload_t
* current_transform
;
348 iterator
->current(iterator
,(void **) ¤t_transform
);
349 length
+= current_transform
->get_length(current_transform
);
352 iterator
->destroy(iterator
);
354 length
+= this->spi
.len
;
355 this->transforms_count
= transforms_count
;
356 this->proposal_length
= length
;
362 * Implements proposal_substructure_t's clone function.
363 * See #proposal_substructure_s.clone for description.
365 static status_t
clone(private_proposal_substructure_t
*this, private_proposal_substructure_t
**clone
)
367 private_proposal_substructure_t
* new_clone
;
368 linked_list_iterator_t
*transforms
;
371 new_clone
= (private_proposal_substructure_t
*) proposal_substructure_create();
373 new_clone
->next_payload
= this->next_payload
;
374 new_clone
->proposal_number
= this->proposal_number
;
375 new_clone
->protocol_id
= this->protocol_id
;
376 new_clone
->spi_size
= this->spi_size
;
377 if (this->spi
.ptr
!= NULL
)
379 new_clone
->spi
.ptr
= allocator_clone_bytes(this->spi
.ptr
,this->spi
.len
);
380 if (new_clone
->spi
.ptr
== NULL
)
382 new_clone
->public.destroy(&(new_clone
->public));
385 new_clone
->spi
.len
= this->spi
.len
;
388 status
= this->transforms
->create_iterator(this->transforms
,&transforms
,FALSE
);
389 if (status
!= SUCCESS
)
391 new_clone
->public.destroy(&(new_clone
->public));
395 while (transforms
->has_next(transforms
))
397 transform_substructure_t
*current_transform
;
398 transform_substructure_t
*current_transform_clone
;
399 status
= transforms
->current(transforms
,(void **) ¤t_transform
);
400 if (status
!= SUCCESS
)
402 transforms
->destroy(transforms
);
403 new_clone
->public.destroy(&(new_clone
->public));
406 status
= current_transform
->clone(current_transform
,¤t_transform_clone
);
407 if (status
!= SUCCESS
)
409 transforms
->destroy(transforms
);
410 new_clone
->public.destroy(&(new_clone
->public));
414 status
= new_clone
->public.add_transform_substructure(&(new_clone
->public),current_transform_clone
);
415 if (status
!= SUCCESS
)
417 transforms
->destroy(transforms
);
418 current_transform_clone
->destroy(current_transform_clone
);
419 new_clone
->public.destroy(&(new_clone
->public));
424 transforms
->destroy(transforms
);
432 * Implements payload_t's and proposal_substructure_t's destroy function.
433 * See #payload_s.destroy or proposal_substructure_s.destroy for description.
435 static status_t
destroy(private_proposal_substructure_t
*this)
437 /* all proposals are getting destroyed */
438 while (this->transforms
->get_count(this->transforms
) > 0)
440 transform_substructure_t
*current_transform
;
441 if (this->transforms
->remove_last(this->transforms
,(void **)¤t_transform
) != SUCCESS
)
445 current_transform
->destroy(current_transform
);
447 this->transforms
->destroy(this->transforms
);
449 if (this->spi
.ptr
!= NULL
)
451 allocator_free(this->spi
.ptr
);
454 allocator_free(this);
460 * Described in header
462 proposal_substructure_t
*proposal_substructure_create()
464 private_proposal_substructure_t
*this = allocator_alloc_thing(private_proposal_substructure_t
);
470 /* interface functions */
471 this->public.payload_interface
.verify
= (status_t (*) (payload_t
*))verify
;
472 this->public.payload_interface
.get_encoding_rules
= (status_t (*) (payload_t
*, encoding_rule_t
**, size_t *) ) get_encoding_rules
;
473 this->public.payload_interface
.get_length
= (size_t (*) (payload_t
*)) get_length
;
474 this->public.payload_interface
.get_next_type
= (payload_type_t (*) (payload_t
*)) get_next_type
;
475 this->public.payload_interface
.set_next_type
= (status_t (*) (payload_t
*,payload_type_t
)) set_next_type
;
476 this->public.payload_interface
.get_type
= (payload_type_t (*) (payload_t
*)) get_type
;
477 this->public.payload_interface
.destroy
= (status_t (*) (payload_t
*))destroy
;
479 /* public functions */
480 this->public.create_transform_substructure_iterator
= (status_t (*) (proposal_substructure_t
*,linked_list_iterator_t
**,bool)) create_transform_substructure_iterator
;
481 this->public.add_transform_substructure
= (status_t (*) (proposal_substructure_t
*,transform_substructure_t
*)) add_transform_substructure
;
482 this->public.set_proposal_number
= (status_t (*) (proposal_substructure_t
*,u_int8_t
))set_proposal_number
;
483 this->public.get_proposal_number
= (u_int8_t (*) (proposal_substructure_t
*)) get_proposal_number
;
484 this->public.set_protocol_id
= (status_t (*) (proposal_substructure_t
*,u_int8_t
))set_protocol_id
;
485 this->public.get_protocol_id
= (u_int8_t (*) (proposal_substructure_t
*)) get_protocol_id
;
486 this->public.set_spi
= (status_t (*) (proposal_substructure_t
*,chunk_t
))set_spi
;
487 this->public.get_spi
= (chunk_t (*) (proposal_substructure_t
*)) get_spi
;
488 this->public.clone
= (status_t (*) (proposal_substructure_t
*, proposal_substructure_t
**)) clone
;
489 this->public.destroy
= (status_t (*) (proposal_substructure_t
*)) destroy
;
491 /* private functions */
492 this->compute_length
= compute_length
;
494 /* set default values of the fields */
495 this->next_payload
= NO_PAYLOAD
;
496 this->proposal_length
= 0;
497 this->proposal_number
= 0;
498 this->protocol_id
= 0;
499 this->transforms_count
= 0;
501 this->spi
.ptr
= NULL
;
504 this->transforms
= linked_list_create();
506 if (this->transforms
== NULL
)
508 allocator_free(this);
511 return (&(this->public));