2 * @file proposal_substructure.h
4 * @brief Implementation of proposal_substructure_t.
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
26 #include "proposal_substructure.h"
28 #include <encoding/payloads/encodings.h>
29 #include <encoding/payloads/transform_substructure.h>
31 #include <utils/allocator.h>
32 #include <utils/linked_list.h>
34 typedef struct private_proposal_substructure_t private_proposal_substructure_t
;
37 * Private data of an proposal_substructure_t object.
40 struct private_proposal_substructure_t
{
42 * Public proposal_substructure_t interface.
44 proposal_substructure_t
public;
49 u_int8_t next_payload
;
52 * Length of this payload.
54 u_int16_t proposal_length
;
59 u_int8_t proposal_number
;
67 * SPI size of the following SPI.
72 * Number of transforms.
74 u_int8_t transforms_count
;
77 * SPI is stored as chunk.
82 * Transforms are stored in a linked_list_t.
84 linked_list_t
* transforms
;
87 * @brief Computes the length of this substructure.
89 * @param this calling private_proposal_substructure_t object
91 void (*compute_length
) (private_proposal_substructure_t
*this);
95 * Encoding rules to parse or generate a Proposal substructure.
97 * The defined offsets are the positions in a object of type
98 * private_proposal_substructure_t.
101 encoding_rule_t proposal_substructure_encodings
[] = {
102 /* 1 Byte next payload type, stored in the field next_payload */
103 { U_INT_8
, offsetof(private_proposal_substructure_t
, next_payload
) },
104 /* Reserved Byte is skipped */
105 { RESERVED_BYTE
, 0 },
106 /* Length of the whole proposal substructure payload*/
107 { PAYLOAD_LENGTH
, offsetof(private_proposal_substructure_t
, proposal_length
) },
108 /* proposal number is a number of 8 bit */
109 { U_INT_8
, offsetof(private_proposal_substructure_t
, proposal_number
) },
110 /* protocol ID is a number of 8 bit */
111 { U_INT_8
, offsetof(private_proposal_substructure_t
, protocol_id
) },
112 /* SPI Size has its own type */
113 { SPI_SIZE
, offsetof(private_proposal_substructure_t
, spi_size
) },
114 /* Number of transforms is a number of 8 bit */
115 { U_INT_8
, offsetof(private_proposal_substructure_t
, transforms_count
) },
116 /* SPI is a chunk of variable size*/
117 { SPI
, offsetof(private_proposal_substructure_t
, spi
) },
118 /* Transforms are stored in a transform substructure,
119 offset points to a linked_list_t pointer */
120 { TRANSFORMS
, offsetof(private_proposal_substructure_t
, transforms
) }
125 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
126 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
127 ! 0 (last) or 2 ! RESERVED ! Proposal Length !
128 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
129 ! Proposal # ! Protocol ID ! SPI Size !# of Transforms!
130 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
132 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
136 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
140 * Implementation of payload_t.verify.
142 static status_t
verify(private_proposal_substructure_t
*this)
144 if ((this->next_payload
!= NO_PAYLOAD
) && (this->next_payload
!= PROPOSAL_SUBSTRUCTURE
))
149 if (this->transforms_count
!= this->transforms
->get_count(this->transforms
))
151 /* must be the same! */
155 if (this->protocol_id
> 4)
157 /* reserved are not supported */
161 /* proposal number is checked in SA payload */
166 * Implementation of payload_t.get_encoding_rules.
168 static void get_encoding_rules(private_proposal_substructure_t
*this, encoding_rule_t
**rules
, size_t *rule_count
)
170 *rules
= proposal_substructure_encodings
;
171 *rule_count
= sizeof(proposal_substructure_encodings
) / sizeof(encoding_rule_t
);
175 * Implementation of payload_t.get_type.
177 static payload_type_t
get_type(private_proposal_substructure_t
*this)
179 return PROPOSAL_SUBSTRUCTURE
;
183 * Implementation of payload_t.get_next_type.
185 static payload_type_t
get_next_type(private_proposal_substructure_t
*this)
187 return (this->next_payload
);
191 * Implementation of payload_t.set_next_type.
193 static void set_next_type(private_proposal_substructure_t
*this,payload_type_t type
)
198 * Implementation of payload_t.get_length.
200 static size_t get_length(private_proposal_substructure_t
*this)
202 return this->proposal_length
;
206 * Implementation of proposal_substructure_t.create_transform_substructure_iterator.
208 static iterator_t
*create_transform_substructure_iterator (private_proposal_substructure_t
*this,bool forward
)
210 return (this->transforms
->create_iterator(this->transforms
,forward
));
214 * Implementation of proposal_substructure_t.add_transform_substructure.
216 static void add_transform_substructure (private_proposal_substructure_t
*this,transform_substructure_t
*transform
)
219 if (this->transforms
->get_count(this->transforms
) > 0)
221 transform_substructure_t
*last_transform
;
222 status
= this->transforms
->get_last(this->transforms
,(void **) &last_transform
);
223 /* last transform is now not anymore last one */
224 last_transform
->set_is_last_transform(last_transform
,FALSE
);
227 transform
->set_is_last_transform(transform
,TRUE
);
229 this->transforms
->insert_last(this->transforms
,(void *) transform
);
230 this->compute_length(this);
234 * Implementation of proposal_substructure_t.set_proposal_number.
236 static void set_proposal_number(private_proposal_substructure_t
*this,u_int8_t proposal_number
)
238 this->proposal_number
= proposal_number
;
242 * Implementation of proposal_substructure_t.get_proposal_number.
244 static u_int8_t
get_proposal_number (private_proposal_substructure_t
*this)
246 return (this->proposal_number
);
250 * Implementation of proposal_substructure_t.set_protocol_id.
252 static void set_protocol_id(private_proposal_substructure_t
*this,u_int8_t protocol_id
)
254 this->protocol_id
= protocol_id
;
258 * Implementation of proposal_substructure_t.get_protocol_id.
260 static u_int8_t
get_protocol_id (private_proposal_substructure_t
*this)
262 return (this->protocol_id
);
266 * Implementation of proposal_substructure_t.set_spi.
268 static void set_spi (private_proposal_substructure_t
*this, chunk_t spi
)
270 /* first delete already set spi value */
271 if (this->spi
.ptr
!= NULL
)
273 allocator_free(this->spi
.ptr
);
274 this->spi
.ptr
= NULL
;
276 this->compute_length(this);
279 this->spi
.ptr
= allocator_clone_bytes(spi
.ptr
,spi
.len
);
280 this->spi
.len
= spi
.len
;
281 this->spi_size
= spi
.len
;
282 this->compute_length(this);
286 * Implementation of proposal_substructure_t.get_spi.
288 static chunk_t
get_spi (private_proposal_substructure_t
*this)
291 spi
.ptr
= this->spi
.ptr
;
292 spi
.len
= this->spi
.len
;
298 * Implementation of proposal_substructure_t.get_info_for_transform_type.
300 static status_t
get_info_for_transform_type (private_proposal_substructure_t
*this,transform_type_t type
, u_int16_t
*transform_id
, u_int16_t
*key_length
)
302 iterator_t
*iterator
;
304 u_int16_t found_transform_id
;
305 u_int16_t found_key_length
;
307 iterator
= this->transforms
->create_iterator(this->transforms
,TRUE
);
309 while (iterator
->has_next(iterator
))
311 transform_substructure_t
*current_transform
;
312 status
= iterator
->current(iterator
,(void **) ¤t_transform
);
313 if (status
!= SUCCESS
)
317 if (current_transform
->get_transform_type(current_transform
) == type
)
319 /* now get data for specific type */
320 found_transform_id
= current_transform
->get_transform_id(current_transform
);
321 status
= current_transform
->get_key_length(current_transform
,&found_key_length
);
322 *transform_id
= found_transform_id
;
323 *key_length
= found_key_length
;
324 iterator
->destroy(iterator
);
328 iterator
->destroy(iterator
);
333 * Implementation of private_proposal_substructure_t.compute_length.
335 static void compute_length (private_proposal_substructure_t
*this)
337 iterator_t
*iterator
;
338 size_t transforms_count
= 0;
339 size_t length
= PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH
;
340 iterator
= this->transforms
->create_iterator(this->transforms
,TRUE
);
341 while (iterator
->has_next(iterator
))
343 payload_t
* current_transform
;
344 iterator
->current(iterator
,(void **) ¤t_transform
);
345 length
+= current_transform
->get_length(current_transform
);
348 iterator
->destroy(iterator
);
350 length
+= this->spi
.len
;
351 this->transforms_count
= transforms_count
;
352 this->proposal_length
= length
;
357 * Implementation of proposal_substructure_t.clone.
359 static private_proposal_substructure_t
* clone(private_proposal_substructure_t
*this)
361 private_proposal_substructure_t
* new_clone
;
362 iterator_t
*transforms
;
364 new_clone
= (private_proposal_substructure_t
*) proposal_substructure_create();
366 new_clone
->next_payload
= this->next_payload
;
367 new_clone
->proposal_number
= this->proposal_number
;
368 new_clone
->protocol_id
= this->protocol_id
;
369 new_clone
->spi_size
= this->spi_size
;
370 if (this->spi
.ptr
!= NULL
)
372 new_clone
->spi
.ptr
= allocator_clone_bytes(this->spi
.ptr
,this->spi
.len
);
373 new_clone
->spi
.len
= this->spi
.len
;
376 transforms
= this->transforms
->create_iterator(this->transforms
,FALSE
);
378 while (transforms
->has_next(transforms
))
380 transform_substructure_t
*current_transform
;
381 transform_substructure_t
*current_transform_clone
;
383 transforms
->current(transforms
,(void **) ¤t_transform
);
385 current_transform_clone
= current_transform
->clone(current_transform
);
387 new_clone
->public.add_transform_substructure(&(new_clone
->public),current_transform_clone
);
390 transforms
->destroy(transforms
);
396 * Implements payload_t's and proposal_substructure_t's destroy function.
397 * See #payload_s.destroy or proposal_substructure_s.destroy for description.
399 static status_t
destroy(private_proposal_substructure_t
*this)
401 /* all proposals are getting destroyed */
402 while (this->transforms
->get_count(this->transforms
) > 0)
404 transform_substructure_t
*current_transform
;
405 if (this->transforms
->remove_last(this->transforms
,(void **)¤t_transform
) != SUCCESS
)
409 current_transform
->destroy(current_transform
);
411 this->transforms
->destroy(this->transforms
);
413 if (this->spi
.ptr
!= NULL
)
415 allocator_free(this->spi
.ptr
);
418 allocator_free(this);
424 * Described in header.
426 proposal_substructure_t
*proposal_substructure_create()
428 private_proposal_substructure_t
*this = allocator_alloc_thing(private_proposal_substructure_t
);
430 /* interface functions */
431 this->public.payload_interface
.verify
= (status_t (*) (payload_t
*))verify
;
432 this->public.payload_interface
.get_encoding_rules
= (void (*) (payload_t
*, encoding_rule_t
**, size_t *) ) get_encoding_rules
;
433 this->public.payload_interface
.get_length
= (size_t (*) (payload_t
*)) get_length
;
434 this->public.payload_interface
.get_next_type
= (payload_type_t (*) (payload_t
*)) get_next_type
;
435 this->public.payload_interface
.set_next_type
= (void (*) (payload_t
*,payload_type_t
)) set_next_type
;
436 this->public.payload_interface
.get_type
= (payload_type_t (*) (payload_t
*)) get_type
;
437 this->public.payload_interface
.destroy
= (void (*) (payload_t
*))destroy
;
439 /* public functions */
440 this->public.create_transform_substructure_iterator
= (iterator_t
* (*) (proposal_substructure_t
*,bool)) create_transform_substructure_iterator
;
441 this->public.add_transform_substructure
= (void (*) (proposal_substructure_t
*,transform_substructure_t
*)) add_transform_substructure
;
442 this->public.set_proposal_number
= (void (*) (proposal_substructure_t
*,u_int8_t
))set_proposal_number
;
443 this->public.get_proposal_number
= (u_int8_t (*) (proposal_substructure_t
*)) get_proposal_number
;
444 this->public.set_protocol_id
= (void (*) (proposal_substructure_t
*,u_int8_t
))set_protocol_id
;
445 this->public.get_protocol_id
= (u_int8_t (*) (proposal_substructure_t
*)) get_protocol_id
;
446 this->public.get_info_for_transform_type
= (status_t (*) (proposal_substructure_t
*,transform_type_t
,u_int16_t
*, u_int16_t
*))get_info_for_transform_type
;
447 this->public.set_spi
= (void (*) (proposal_substructure_t
*,chunk_t
))set_spi
;
448 this->public.get_spi
= (chunk_t (*) (proposal_substructure_t
*)) get_spi
;
449 this->public.clone
= (proposal_substructure_t
* (*) (proposal_substructure_t
*)) clone
;
450 this->public.destroy
= (void (*) (proposal_substructure_t
*)) destroy
;
453 /* private functions */
454 this->compute_length
= compute_length
;
456 /* set default values of the fields */
457 this->next_payload
= NO_PAYLOAD
;
458 this->proposal_length
= 0;
459 this->proposal_number
= 0;
460 this->protocol_id
= 0;
461 this->transforms_count
= 0;
463 this->spi
.ptr
= NULL
;
466 this->transforms
= linked_list_create();
468 return (&(this->public));