4 * @brief Generic generator class used to generate IKEv2-Header and Payload
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 <pluto/constants.h>
27 #include <pluto/defs.h>
29 #include "allocator.h"
31 #include "generator.h"
35 * buffer_t: used for geneartor operations
37 typedef struct generator_infos_s generator_infos_t
;
39 struct generator_infos_s
{
42 * Buffer used to generate to
47 * current write position in buffer (one byte alligned)
49 u_int8_t
*out_position
;
52 * position of last byte in buffer
54 u_int8_t
*roof_position
;
57 * Current bit writing to
62 * Associated data struct to read informations from
66 * @brief Destroys a generator_infos_t object
68 * @param generator_infos_t generator_infos_t object
69 * @return SUCCESSFUL if succeeded, FAILED otherwise
71 status_t (*destroy
) (generator_infos_t
*this);
74 * Checks if enough space is available in buffer and if not,
75 * the buffer size is increased until at least the asked amount of space
78 * @param bits number of bits to make at leas available in buffer
79 * @param generator_infos_t generator_infos_t object
80 * @return SUCCESSFUL if succeeded, OUT_OF_RES otherwise
82 status_t (*make_space_available
) (generator_infos_t
*this,size_t bits
);
84 status_t (*write_bytes_to_buffer
) (generator_infos_t
*this,void * bytes
,size_t number_of_bytes
);
86 status_t (*write_chunk
) (generator_infos_t
*this,chunk_t
*data
);
90 * implements generator_infos_t's increase_buffer function
92 static status_t
generator_info_make_space_available (generator_infos_t
*this, size_t bits
)
94 size_t free_bits
= ((this->roof_position
- this->out_position
) * 8) - this->current_bit
;
96 while (free_bits
< bits
)
98 size_t old_buffer_size
= ((this->roof_position
) - ( this->buffer
));
99 size_t new_buffer_size
= old_buffer_size
+ GENERATOR_DATA_BUFFER_INCREASE_VALUE
;
100 size_t out_position_offset
= ((this->out_position
) - (this->buffer
));
101 u_int8_t
*new_buffer
;
103 new_buffer
= allocator_realloc(this->buffer
,new_buffer_size
);
104 if (new_buffer
== NULL
)
109 this->buffer
= new_buffer
;
111 this->out_position
= (this->buffer
+ out_position_offset
);
112 this->roof_position
= (this->buffer
+ new_buffer_size
);
118 static status_t
generator_info_write_bytes_to_buffer (generator_infos_t
*this,void * bytes
,size_t number_of_bytes
)
120 u_int8_t
*read_position
= (u_int8_t
*) bytes
;
124 status
= this->make_space_available(this,number_of_bytes
* 8);
126 if (status
!= SUCCESS
)
131 for (i
= 0; i
< number_of_bytes
; i
++)
133 *(this->out_position
) = *(read_position
);
135 this->out_position
++;
140 static status_t
generator_infos_write_chunk (generator_infos_t
*this,chunk_t
*data
)
142 size_t data_length
= this->out_position
- this->buffer
;
143 if (this->current_bit
> 0)
145 data
->ptr
= allocator_alloc(data_length
);
146 if (data
->ptr
== NULL
)
151 memcpy(data
->ptr
,this->buffer
,data_length
);
152 data
->len
= data_length
;
157 static status_t
generator_infos_destroy (generator_infos_t
*this)
163 allocator_free(this->buffer
);
164 allocator_free(this);
169 * Creates a generator_infos_t-object holding necessary informations
170 * for generating (buffer, data_struct, etc)
172 * @param data_struct where to read the data out
174 generator_infos_t
* generator_infos_create(void *data_struct
)
176 generator_infos_t
*this = allocator_alloc_thing(generator_infos_t
);
184 this->destroy
= generator_infos_destroy
;
185 this->make_space_available
= generator_info_make_space_available
;
186 this->write_chunk
= generator_infos_write_chunk
;
187 this->write_bytes_to_buffer
= generator_info_write_bytes_to_buffer
;
189 /* allocate memory for buffer */
190 this->buffer
= allocator_alloc(GENERATOR_DATA_BUFFER_SIZE
);
191 if (this->buffer
== NULL
)
193 allocator_free(this);
197 /* set private data */
198 this->out_position
= this->buffer
;
199 this->roof_position
= this->buffer
+ GENERATOR_DATA_BUFFER_SIZE
;
200 this->data_struct
= data_struct
;
201 this->current_bit
= 0;
208 * Private data of a generator_t object
210 typedef struct private_generator_s private_generator_t
;
212 struct private_generator_s
{
214 * Public part of a generator object
218 /* private functions and fields */
221 * Generates a chunk_t with specific encoding rules
223 * items are bytewhise written
225 * @param this private_generator_t-object
226 * @param data_struct data_struct to read data from
227 * @param encoding_rules pointer to first encoding_rule of encoding rules array
228 * @param encoding_rules_count number of encoding rules in encoding rules array
229 * @param data pointer to chunk where to write the data in
231 * @return SUCCESS if succeeded,
232 * OUT_OF_RES if out of ressources
234 status_t (*generate
) (private_generator_t
*this,void * data_struct
,encoding_rule_t
*encoding_rules
, size_t encoding_rules_count
, chunk_t
*data
);
239 status_t (*generate_u_int_type
) (private_generator_t
*this,encoding_type_t int_type
,u_int32_t offset
, generator_infos_t
*generator_infos
);
242 * Pointer to the payload informations needed to automatic
243 * generate a specific payload type
245 payload_info_t
**payload_infos
;
249 * implements private_generator_t's double_buffer function
251 static status_t
generate_u_int_type (private_generator_t
*this,encoding_type_t int_type
,u_int32_t offset
,generator_infos_t
*generator_infos
)
253 size_t number_of_bits
= 0;
277 if (((number_of_bits
% 8) == 0) && (generator_infos
->current_bit
!= 0))
279 /* current bit has to be zero for values greater then 4 bits */
283 status
= generator_infos
->make_space_available(generator_infos
,number_of_bits
);
285 if (status
!= SUCCESS
)
294 if (generator_infos
->current_bit
== 0)
296 u_int8_t high_val
= *((u_int8_t
*)(generator_infos
->data_struct
+ offset
)) << 4;
297 u_int8_t low_val
= *(generator_infos
->out_position
) & 0x0F;
299 *(generator_infos
->out_position
) = high_val
| low_val
;
300 /* write position is not changed, just bit position is moved */
301 generator_infos
->current_bit
= 4;
303 else if (generator_infos
->current_bit
== 4)
305 u_int high_val
= *(generator_infos
->out_position
) & 0xF0;
306 u_int low_val
= *((u_int8_t
*)(generator_infos
->data_struct
+ offset
)) & 0x0F;
307 *(generator_infos
->out_position
) = high_val
| low_val
;
308 generator_infos
->out_position
++;
309 generator_infos
->current_bit
= 0;
314 /* 4 Bit integers must have a 4 bit alignment */
322 *generator_infos
->out_position
= *((u_int8_t
*)(generator_infos
->data_struct
+ offset
));
323 generator_infos
->out_position
++;
329 u_int16_t int16_val
= htons(*((u_int16_t
*)(generator_infos
->data_struct
+ offset
)));
330 generator_infos
->write_bytes_to_buffer(generator_infos
,&int16_val
,sizeof(u_int16_t
));
336 u_int32_t int32_val
= htonl(*((u_int32_t
*)(generator_infos
->data_struct
+ offset
)));
337 generator_infos
->write_bytes_to_buffer(generator_infos
,&int32_val
,sizeof(u_int32_t
));
342 u_int32_t int32_val_low
= htonl(*((u_int32_t
*)(generator_infos
->data_struct
+ offset
)));
343 u_int32_t int32_val_high
= htonl(*((u_int32_t
*)(generator_infos
->data_struct
+ offset
) + 1));
344 generator_infos
->write_bytes_to_buffer(generator_infos
,&int32_val_high
,sizeof(u_int32_t
));
345 generator_infos
->write_bytes_to_buffer(generator_infos
,&int32_val_low
,sizeof(u_int32_t
));
358 * implements private_generator_t's generate function
360 static status_t
generate (private_generator_t
*this,void * data_struct
,encoding_rule_t
*encoding_rules
, size_t encoding_rules_count
, chunk_t
*data
)
366 generator_infos_t
*infos
= generator_infos_create(data_struct
);
374 for (i
= 0; i
< encoding_rules_count
;i
++)
377 switch (encoding_rules
[i
].type
)
379 /* all u int values are generated in generate_u_int_type */
385 status
= this->generate_u_int_type(this,encoding_rules
[i
].type
,encoding_rules
[i
].offset
,infos
);
389 u_int8_t reserved_bit
= ~(1 << (7 - infos
->current_bit
));
391 *(infos
->out_position
) = *(infos
->out_position
) & reserved_bit
;
393 infos
->current_bit
++;
394 if (infos
->current_bit
>= 8)
396 infos
->current_bit
= infos
->current_bit
% 8;
397 status
= infos
->make_space_available(infos
,8);
398 infos
->out_position
++;
404 if (infos
->current_bit
> 0)
408 *(infos
->out_position
) = 0x00;
409 infos
->out_position
++;
414 u_int8_t flag_value
= (*((bool *) (infos
->data_struct
+ encoding_rules
[i
].offset
))) ?
1 : 0;
415 u_int8_t flag
= (flag_value
<< (7 - infos
->current_bit
));
417 *(infos
->out_position
) = *(infos
->out_position
) | flag
;
419 infos
->current_bit
++;
420 if (infos
->current_bit
>= 8)
422 infos
->current_bit
= infos
->current_bit
% 8;
423 status
= infos
->make_space_available(infos
,8);
424 infos
->out_position
++;
429 /* length is generated like an U_INT_32 */
430 status
= this->generate_u_int_type(this,U_INT_32
,encoding_rules
[i
].offset
,infos
);
432 /* actually not implemented */
436 if (status
!= SUCCESS
)
438 infos
->destroy(infos
);
444 status
= infos
->write_chunk(infos
,data
);
445 infos
->destroy(infos
);
449 static status_t
generate_payload (private_generator_t
*this,payload_type_t payload_type
,void * data_struct
, chunk_t
*data
)
453 /* check every payload info for specific type */
454 for (i
= 0; this->payload_infos
[i
] != NULL
; i
++)
456 if (this->payload_infos
[i
]->payload_type
== payload_type
)
458 /* found payload informations, generating is done in private function generate() */
459 return (this->generate(this, data_struct
,this->payload_infos
[i
]->ecoding_rules
,this->payload_infos
[i
]->encoding_rules_count
,data
));
462 return NOT_SUPPORTED
;
466 * Implementation of generator_t's destroy function
468 static status_t
destroy(private_generator_t
*this)
475 allocator_free(this);
480 * Described in header
482 generator_t
* generator_create(payload_info_t
** payload_infos
)
484 private_generator_t
*this;
486 if (payload_infos
== NULL
)
491 this = allocator_alloc_thing(private_generator_t
);
497 /* initiate public functions */
498 this->public.generate_payload
= (status_t(*)(generator_t
*, payload_type_t
, void *, chunk_t
*)) generate_payload
;
499 this->public.destroy
= (status_t(*)(generator_t
*)) destroy
;
501 /* initiate private functions */
502 this->generate
= generate
;
503 this->generate_u_int_type
= generate_u_int_type
;
505 /* initiate private variables */
506 this->payload_infos
= payload_infos
;
508 return &(this->public);