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 "encodings.h"
31 #include "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 and proposal_substructure_t's destroy function.
174 * See #payload_s.destroy or proposal_substructure_s.destroy for description.
176 static status_t
destroy(private_proposal_substructure_t
*this)
178 /* all proposals are getting destroyed */
179 while (this->transforms
->get_count(this->transforms
) > 0)
181 transform_substructure_t
*current_transform
;
182 if (this->transforms
->remove_last(this->transforms
,(void **)¤t_transform
) != SUCCESS
)
186 current_transform
->destroy(current_transform
);
188 this->transforms
->destroy(this->transforms
);
190 if (this->spi
.ptr
!= NULL
)
192 allocator_free(this->spi
.ptr
);
195 allocator_free(this);
201 * Implements payload_t's get_encoding_rules function.
202 * See #payload_s.get_encoding_rules for description.
204 static status_t
get_encoding_rules(private_proposal_substructure_t
*this, encoding_rule_t
**rules
, size_t *rule_count
)
206 *rules
= proposal_substructure_encodings
;
207 *rule_count
= sizeof(proposal_substructure_encodings
) / sizeof(encoding_rule_t
);
213 * Implements payload_t's get_type function.
214 * See #payload_s.get_type for description.
216 static payload_type_t
get_type(private_proposal_substructure_t
*this)
218 return PROPOSAL_SUBSTRUCTURE
;
222 * Implements payload_t's get_next_type function.
223 * See #payload_s.get_next_type for description.
225 static payload_type_t
get_next_type(private_proposal_substructure_t
*this)
227 return (this->next_payload
);
231 * Implements payload_t's set_next_type function.
232 * See #payload_s.set_next_type for description.
234 static status_t
set_next_type(private_proposal_substructure_t
*this,payload_type_t type
)
240 * Implements payload_t's get_length function.
241 * See #payload_s.get_length for description.
243 static size_t get_length(private_proposal_substructure_t
*this)
245 return this->proposal_length
;
249 * Implements proposal_substructure_t's create_transform_substructure_iterator function.
250 * See #proposal_substructure_s.create_transform_substructure_iterator for description.
252 static status_t
create_transform_substructure_iterator (private_proposal_substructure_t
*this,linked_list_iterator_t
**iterator
,bool forward
)
254 return (this->transforms
->create_iterator(this->transforms
,iterator
,forward
));
258 * Implements proposal_substructure_t's add_transform_substructure function.
259 * See #proposal_substructure_s.add_transform_substructure for description.
261 static status_t
add_transform_substructure (private_proposal_substructure_t
*this,transform_substructure_t
*transform
)
264 if (this->transforms
->get_count(this->transforms
) > 0)
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
);
272 transform
->set_is_last_transform(transform
,TRUE
);
274 status
= this->transforms
->insert_last(this->transforms
,(void *) transform
);
275 this->compute_length(this);
280 * Implements proposal_substructure_t's set_proposal_number function.
281 * See #proposal_substructure_s.set_proposal_number for description.
283 static status_t
set_proposal_number(private_proposal_substructure_t
*this,u_int8_t proposal_number
)
285 this->proposal_number
= proposal_number
;
290 * Implements proposal_substructure_t's get_proposal_number function.
291 * See #proposal_substructure_s.get_proposal_number for description.
293 static u_int8_t
get_proposal_number (private_proposal_substructure_t
*this)
295 return (this->proposal_number
);
299 * Implements proposal_substructure_t's set_protocol_id function.
300 * See #proposal_substructure_s.set_protocol_id for description.
302 static status_t
set_protocol_id(private_proposal_substructure_t
*this,u_int8_t protocol_id
)
304 this->protocol_id
= protocol_id
;
309 * Implements proposal_substructure_t's get_protocol_id function.
310 * See #proposal_substructure_s.get_protocol_id for description.
312 static u_int8_t
get_protocol_id (private_proposal_substructure_t
*this)
314 return (this->protocol_id
);
319 * Implements proposal_substructure_t's set_spi function.
320 * See #proposal_substructure_s.set_spi for description.
322 static status_t
set_spi (private_proposal_substructure_t
*this, chunk_t spi
)
324 /* first delete already set spi value */
325 if (this->spi
.ptr
!= NULL
)
327 allocator_free(this->spi
.ptr
);
328 this->spi
.ptr
= NULL
;
330 this->compute_length(this);
333 this->spi
.ptr
= allocator_clone_bytes(spi
.ptr
,spi
.len
);
334 if (this->spi
.ptr
== NULL
)
338 this->spi
.len
= spi
.len
;
339 this->spi_size
= spi
.len
;
340 this->compute_length(this);
346 * Implements proposal_substructure_t's get_spi function.
347 * See #proposal_substructure_s.get_spi for description.
349 static chunk_t
get_spi (private_proposal_substructure_t
*this)
352 spi
.ptr
= this->spi
.ptr
;
353 spi
.len
= this->spi
.len
;
359 * Implements private_proposal_substructure_t's compute_length function.
360 * See #private_proposal_substructure_s.compute_length for description.
362 static status_t
compute_length (private_proposal_substructure_t
*this)
364 linked_list_iterator_t
*iterator
;
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
)
373 while (iterator
->has_next(iterator
))
375 payload_t
* current_transform
;
376 iterator
->current(iterator
,(void **) ¤t_transform
);
377 length
+= current_transform
->get_length(current_transform
);
380 iterator
->destroy(iterator
);
382 length
+= this->spi
.len
;
383 this->transforms_count
= transforms_count
;
384 this->proposal_length
= length
;
391 * Described in header
393 proposal_substructure_t
*proposal_substructure_create()
395 private_proposal_substructure_t
*this = allocator_alloc_thing(private_proposal_substructure_t
);
401 /* interface functions */
402 this->public.payload_interface
.verify
= (status_t (*) (payload_t
*))verify
;
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
;
406 this->public.payload_interface
.set_next_type
= (status_t (*) (payload_t
*,payload_type_t
)) set_next_type
;
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
;
410 /* public functions */
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
;
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
;
419 this->public.destroy
= (status_t (*) (proposal_substructure_t
*)) destroy
;
421 /* private functions */
422 this->compute_length
= compute_length
;
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;
431 this->spi
.ptr
= NULL
;
434 this->transforms
= linked_list_create();
436 if (this->transforms
== NULL
)
438 allocator_free(this);
441 return (&(this->public));