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
) }
130 * Implements payload_t's and proposal_substructure_t's destroy function.
131 * See #payload_s.destroy or proposal_substructure_s.destroy for description.
133 static status_t
destroy(private_proposal_substructure_t
*this)
135 /* all proposals are getting destroyed */
136 while (this->transforms
->get_count(this->transforms
) > 0)
138 transform_substructure_t
*current_transform
;
139 if (this->transforms
->remove_last(this->transforms
,(void **)¤t_transform
) != SUCCESS
)
143 current_transform
->destroy(current_transform
);
145 this->transforms
->destroy(this->transforms
);
147 if (this->spi
.ptr
!= NULL
)
149 allocator_free(this->spi
.ptr
);
152 allocator_free(this);
158 * Implements payload_t's get_encoding_rules function.
159 * See #payload_s.get_encoding_rules for description.
161 static status_t
get_encoding_rules(private_proposal_substructure_t
*this, encoding_rule_t
**rules
, size_t *rule_count
)
163 *rules
= proposal_substructure_encodings
;
164 *rule_count
= sizeof(proposal_substructure_encodings
) / sizeof(encoding_rule_t
);
170 * Implements payload_t's get_type function.
171 * See #payload_s.get_type for description.
173 static payload_type_t
get_type(private_proposal_substructure_t
*this)
175 return PROPOSAL_SUBSTRUCTURE
;
179 * Implements payload_t's get_next_type function.
180 * See #payload_s.get_next_type for description.
182 static payload_type_t
get_next_type(private_proposal_substructure_t
*this)
184 return (this->next_payload
);
188 * Implements payload_t's set_next_type function.
189 * See #payload_s.set_next_type for description.
191 static status_t
set_next_type(private_proposal_substructure_t
*this,payload_type_t type
)
197 * Implements payload_t's get_length function.
198 * See #payload_s.get_length for description.
200 static size_t get_length(private_proposal_substructure_t
*this)
202 return this->proposal_length
;
206 * Implements proposal_substructure_t's create_transform_substructure_iterator function.
207 * See #proposal_substructure_s.create_transform_substructure_iterator for description.
209 static status_t
create_transform_substructure_iterator (private_proposal_substructure_t
*this,linked_list_iterator_t
**iterator
,bool forward
)
211 return (this->transforms
->create_iterator(this->transforms
,iterator
,forward
));
215 * Implements proposal_substructure_t's add_transform_substructure function.
216 * See #proposal_substructure_s.add_transform_substructure for description.
218 static status_t
add_transform_substructure (private_proposal_substructure_t
*this,transform_substructure_t
*transform
)
221 if (this->transforms
->get_count(this->transforms
) > 0)
223 transform_substructure_t
*last_transform
;
224 status
= this->transforms
->get_last(this->transforms
,(void **) &last_transform
);
225 /* last transform is now not anymore last one */
226 last_transform
->set_is_last_transform(last_transform
,FALSE
);
229 transform
->set_is_last_transform(transform
,TRUE
);
231 status
= this->transforms
->insert_last(this->transforms
,(void *) transform
);
232 this->compute_length(this);
237 * Implements proposal_substructure_t's set_proposal_number function.
238 * See #proposal_substructure_s.set_proposal_number for description.
240 static status_t
set_proposal_number(private_proposal_substructure_t
*this,u_int8_t proposal_number
)
242 this->proposal_number
= proposal_number
;
247 * Implements proposal_substructure_t's get_proposal_number function.
248 * See #proposal_substructure_s.get_proposal_number for description.
250 static u_int8_t
get_proposal_number (private_proposal_substructure_t
*this)
252 return (this->proposal_number
);
256 * Implements proposal_substructure_t's set_protocol_id function.
257 * See #proposal_substructure_s.set_protocol_id for description.
259 static status_t
set_protocol_id(private_proposal_substructure_t
*this,u_int8_t protocol_id
)
261 this->protocol_id
= protocol_id
;
266 * Implements proposal_substructure_t's get_protocol_id function.
267 * See #proposal_substructure_s.get_protocol_id for description.
269 static u_int8_t
get_protocol_id (private_proposal_substructure_t
*this)
271 return (this->protocol_id
);
276 * Implements proposal_substructure_t's set_spi function.
277 * See #proposal_substructure_s.set_spi for description.
279 static status_t
set_spi (private_proposal_substructure_t
*this, chunk_t spi
)
281 /* first delete already set spi value */
282 if (this->spi
.ptr
!= NULL
)
284 allocator_free(this->spi
.ptr
);
285 this->spi
.ptr
= NULL
;
287 this->compute_length(this);
290 this->spi
.ptr
= allocator_clone_bytes(spi
.ptr
,spi
.len
);
291 if (this->spi
.ptr
== NULL
)
295 this->spi
.len
= spi
.len
;
296 this->spi_size
= spi
.len
;
297 this->compute_length(this);
303 * Implements proposal_substructure_t's get_spi function.
304 * See #proposal_substructure_s.get_spi for description.
306 static chunk_t
get_spi (private_proposal_substructure_t
*this)
309 spi
.ptr
= this->spi
.ptr
;
310 spi
.len
= this->spi
.len
;
316 * Implements private_proposal_substructure_t's compute_length function.
317 * See #private_proposal_substructure_s.compute_length for description.
319 static status_t
compute_length (private_proposal_substructure_t
*this)
321 linked_list_iterator_t
*iterator
;
323 size_t transforms_count
= 0;
324 size_t length
= PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH
;
325 status
= this->transforms
->create_iterator(this->transforms
,&iterator
,TRUE
);
326 if (status
!= SUCCESS
)
330 while (iterator
->has_next(iterator
))
332 payload_t
* current_transform
;
333 iterator
->current(iterator
,(void **) ¤t_transform
);
334 length
+= current_transform
->get_length(current_transform
);
337 iterator
->destroy(iterator
);
339 length
+= this->spi
.len
;
340 this->transforms_count
= transforms_count
;
341 this->proposal_length
= length
;
348 * Described in header
350 proposal_substructure_t
*proposal_substructure_create()
352 private_proposal_substructure_t
*this = allocator_alloc_thing(private_proposal_substructure_t
);
358 this->public.payload_interface
.get_encoding_rules
= (status_t (*) (payload_t
*, encoding_rule_t
**, size_t *) ) get_encoding_rules
;
359 this->public.payload_interface
.get_length
= (size_t (*) (payload_t
*)) get_length
;
360 this->public.payload_interface
.get_next_type
= (payload_type_t (*) (payload_t
*)) get_next_type
;
361 this->public.payload_interface
.set_next_type
= (status_t (*) (payload_t
*,payload_type_t
)) set_next_type
;
362 this->public.payload_interface
.get_type
= (payload_type_t (*) (payload_t
*)) get_type
;
363 this->public.payload_interface
.destroy
= (status_t (*) (payload_t
*))destroy
;
364 this->public.create_transform_substructure_iterator
= (status_t (*) (proposal_substructure_t
*,linked_list_iterator_t
**,bool)) create_transform_substructure_iterator
;
365 this->public.add_transform_substructure
= (status_t (*) (proposal_substructure_t
*,transform_substructure_t
*)) add_transform_substructure
;
366 this->public.set_proposal_number
= (status_t (*) (proposal_substructure_t
*,u_int8_t
))set_proposal_number
;
367 this->public.get_proposal_number
= (u_int8_t (*) (proposal_substructure_t
*)) get_proposal_number
;
368 this->public.set_protocol_id
= (status_t (*) (proposal_substructure_t
*,u_int8_t
))set_protocol_id
;
369 this->public.get_protocol_id
= (u_int8_t (*) (proposal_substructure_t
*)) get_protocol_id
;
370 this->public.set_spi
= (status_t (*) (proposal_substructure_t
*,chunk_t
))set_spi
;
371 this->public.get_spi
= (chunk_t (*) (proposal_substructure_t
*)) get_spi
;
372 this->public.destroy
= (status_t (*) (proposal_substructure_t
*)) destroy
;
374 /* private functions */
375 this->compute_length
= compute_length
;
377 /* set default values of the fields */
378 this->next_payload
= NO_PAYLOAD
;
379 this->proposal_length
= 0;
380 this->proposal_number
= 0;
381 this->protocol_id
= 0;
382 this->transforms_count
= 0;
384 this->spi
.ptr
= NULL
;
387 this->transforms
= linked_list_create();
389 if (this->transforms
== NULL
)
391 allocator_free(this);
394 return (&(this->public));