4 * @brief Generic generator class used to generate IKEv2-header and payloads.
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
25 #include <arpa/inet.h>
27 #include "allocator.h"
29 #include "generator.h"
33 * Uused for geneartor operations
35 typedef struct generator_infos_s generator_infos_t
;
37 struct generator_infos_s
{
40 * Buffer used to generate to
45 * current write position in buffer (one byte alligned)
47 u_int8_t
*out_position
;
50 * position of last byte in buffer
52 u_int8_t
*roof_position
;
55 * Current bit writing to
60 * Associated data struct to read informations from
64 * @brief Destroys a generator_infos_t object
66 * @param generator_infos_t generator_infos_t object
67 * @return SUCCESSFUL if succeeded, FAILED otherwise
69 status_t (*destroy
) (generator_infos_t
*this);
72 * Checks if enough space is available in buffer and if not,
73 * the buffer size is increased until at least the asked amount of space
76 * @param bits number of bits to make at leas available in buffer
77 * @param generator_infos_t generator_infos_t object
78 * @return SUCCESSFUL if succeeded, OUT_OF_RES otherwise
80 status_t (*make_space_available
) (generator_infos_t
*this,size_t bits
);
82 status_t (*write_bytes_to_buffer
) (generator_infos_t
*this,void * bytes
,size_t number_of_bytes
);
84 status_t (*write_chunk
) (generator_infos_t
*this,chunk_t
*data
);
88 * implements generator_infos_t's increase_buffer function
90 static status_t
generator_info_make_space_available (generator_infos_t
*this, size_t bits
)
92 while ((((this->roof_position
- this->out_position
) * 8) - this->current_bit
) < bits
)
94 size_t old_buffer_size
= ((this->roof_position
) - ( this->buffer
));
95 size_t new_buffer_size
= old_buffer_size
+ GENERATOR_DATA_BUFFER_INCREASE_VALUE
;
96 size_t out_position_offset
= ((this->out_position
) - (this->buffer
));
99 new_buffer
= allocator_realloc(this->buffer
,new_buffer_size
);
100 if (new_buffer
== NULL
)
105 this->buffer
= new_buffer
;
107 this->out_position
= (this->buffer
+ out_position_offset
);
108 this->roof_position
= (this->buffer
+ new_buffer_size
);
115 static status_t
generator_info_write_bytes_to_buffer (generator_infos_t
*this,void * bytes
,size_t number_of_bytes
)
117 u_int8_t
*read_position
= (u_int8_t
*) bytes
;
121 status
= this->make_space_available(this,number_of_bytes
* 8);
123 if (status
!= SUCCESS
)
128 for (i
= 0; i
< number_of_bytes
; i
++)
130 *(this->out_position
) = *(read_position
);
132 this->out_position
++;
137 static status_t
generator_infos_write_chunk (generator_infos_t
*this,chunk_t
*data
)
139 size_t data_length
= this->out_position
- this->buffer
;
140 if (this->current_bit
> 0)
142 data
->ptr
= allocator_alloc(data_length
);
143 if (data
->ptr
== NULL
)
148 memcpy(data
->ptr
,this->buffer
,data_length
);
149 data
->len
= data_length
;
154 static status_t
generator_infos_destroy (generator_infos_t
*this)
160 allocator_free(this->buffer
);
161 allocator_free(this);
166 * Creates a generator_infos_t object holding necessary informations
167 * for generating (buffer, data_struct, etc)
169 * @param data_struct where to read the data out
171 generator_infos_t
* generator_infos_create(void *data_struct
)
173 generator_infos_t
*this = allocator_alloc_thing(generator_infos_t
);
181 this->destroy
= generator_infos_destroy
;
182 this->make_space_available
= generator_info_make_space_available
;
183 this->write_chunk
= generator_infos_write_chunk
;
184 this->write_bytes_to_buffer
= generator_info_write_bytes_to_buffer
;
186 /* allocate memory for buffer */
187 this->buffer
= allocator_alloc(GENERATOR_DATA_BUFFER_SIZE
);
188 if (this->buffer
== NULL
)
190 allocator_free(this);
194 /* set private data */
195 this->out_position
= this->buffer
;
196 this->roof_position
= this->buffer
+ GENERATOR_DATA_BUFFER_SIZE
;
197 this->data_struct
= data_struct
;
198 this->current_bit
= 0;
205 * Private data of a generator_t object
207 typedef struct private_generator_s private_generator_t
;
209 struct private_generator_s
{
211 * Public part of a generator object
215 /* private functions and fields */
218 * Generates a chunk_t with specific encoding rules
220 * items are bytewhise written
222 * @param this private_generator_t object
223 * @param data_struct data_struct to read data from
224 * @param encoding_rules pointer to first encoding_rule of encoding rules array
225 * @param encoding_rules_count number of encoding rules in encoding rules array
226 * @param data pointer to chunk where to write the data in
228 * @return SUCCESS if succeeded,
229 * OUT_OF_RES if out of ressources
231 status_t (*generate
) (private_generator_t
*this,void * data_struct
,encoding_rule_t
*encoding_rules
, size_t encoding_rules_count
, chunk_t
*data
);
236 status_t (*generate_u_int_type
) (private_generator_t
*this,encoding_type_t int_type
,u_int32_t offset
, generator_infos_t
*generator_infos
);
239 * Pointer to the payload informations needed to automatic
240 * generate a specific payload type
242 payload_info_t
**payload_infos
;
246 * implements private_generator_t's double_buffer function
248 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
)
250 size_t number_of_bits
= 0;
274 if (((number_of_bits
% 8) == 0) && (generator_infos
->current_bit
!= 0))
276 /* current bit has to be zero for values greater then 4 bits */
280 status
= generator_infos
->make_space_available(generator_infos
,number_of_bits
);
282 if (status
!= SUCCESS
)
291 if (generator_infos
->current_bit
== 0)
293 u_int8_t high_val
= *((u_int8_t
*)(generator_infos
->data_struct
+ offset
)) << 4;
294 u_int8_t low_val
= *(generator_infos
->out_position
) & 0x0F;
296 *(generator_infos
->out_position
) = high_val
| low_val
;
297 /* write position is not changed, just bit position is moved */
298 generator_infos
->current_bit
= 4;
300 else if (generator_infos
->current_bit
== 4)
302 u_int high_val
= *(generator_infos
->out_position
) & 0xF0;
303 u_int low_val
= *((u_int8_t
*)(generator_infos
->data_struct
+ offset
)) & 0x0F;
304 *(generator_infos
->out_position
) = high_val
| low_val
;
305 generator_infos
->out_position
++;
306 generator_infos
->current_bit
= 0;
311 /* 4 Bit integers must have a 4 bit alignment */
319 *generator_infos
->out_position
= *((u_int8_t
*)(generator_infos
->data_struct
+ offset
));
320 generator_infos
->out_position
++;
326 u_int16_t int16_val
= htons(*((u_int16_t
*)(generator_infos
->data_struct
+ offset
)));
327 generator_infos
->write_bytes_to_buffer(generator_infos
,&int16_val
,sizeof(u_int16_t
));
333 u_int32_t int32_val
= htonl(*((u_int32_t
*)(generator_infos
->data_struct
+ offset
)));
334 generator_infos
->write_bytes_to_buffer(generator_infos
,&int32_val
,sizeof(u_int32_t
));
339 u_int32_t int32_val_low
= htonl(*((u_int32_t
*)(generator_infos
->data_struct
+ offset
)));
340 u_int32_t int32_val_high
= htonl(*((u_int32_t
*)(generator_infos
->data_struct
+ offset
) + 1));
341 generator_infos
->write_bytes_to_buffer(generator_infos
,&int32_val_high
,sizeof(u_int32_t
));
342 generator_infos
->write_bytes_to_buffer(generator_infos
,&int32_val_low
,sizeof(u_int32_t
));
355 * implements private_generator_t's generate function
357 static status_t
generate (private_generator_t
*this,void * data_struct
,encoding_rule_t
*encoding_rules
, size_t encoding_rules_count
, chunk_t
*data
)
363 generator_infos_t
*infos
= generator_infos_create(data_struct
);
371 for (i
= 0; i
< encoding_rules_count
;i
++)
374 switch (encoding_rules
[i
].type
)
376 /* all u int values are generated in generate_u_int_type */
382 status
= this->generate_u_int_type(this,encoding_rules
[i
].type
,encoding_rules
[i
].offset
,infos
);
386 status
= infos
->make_space_available(infos
,1);
387 u_int8_t reserved_bit
= ~(1 << (7 - infos
->current_bit
));
389 *(infos
->out_position
) = *(infos
->out_position
) & reserved_bit
;
391 infos
->current_bit
++;
392 if (infos
->current_bit
>= 8)
394 infos
->current_bit
= infos
->current_bit
% 8;
395 infos
->out_position
++;
401 status
= infos
->make_space_available(infos
,8);
402 if ((status
!= SUCCESS
) || (infos
->current_bit
> 0))
406 *(infos
->out_position
) = 0x00;
407 infos
->out_position
++;
412 u_int8_t flag_value
= (*((bool *) (infos
->data_struct
+ encoding_rules
[i
].offset
))) ?
1 : 0;
413 u_int8_t flag
= (flag_value
<< (7 - infos
->current_bit
));
415 *(infos
->out_position
) = *(infos
->out_position
) | flag
;
417 infos
->current_bit
++;
418 if (infos
->current_bit
>= 8)
420 infos
->current_bit
= infos
->current_bit
% 8;
421 status
= infos
->make_space_available(infos
,8);
422 infos
->out_position
++;
427 /* length is generated like an U_INT_32 */
428 status
= this->generate_u_int_type(this,U_INT_32
,encoding_rules
[i
].offset
,infos
);
430 /* actually not implemented */
434 if (status
!= SUCCESS
)
436 infos
->destroy(infos
);
442 status
= infos
->write_chunk(infos
,data
);
443 infos
->destroy(infos
);
447 static status_t
generate_payload (private_generator_t
*this,payload_type_t payload_type
,void * data_struct
, chunk_t
*data
)
451 /* check every payload info for specific type */
452 for (i
= 0; this->payload_infos
[i
] != NULL
; i
++)
454 if (this->payload_infos
[i
]->payload_type
== payload_type
)
456 /* found payload informations, generating is done in private function generate() */
457 return (this->generate(this, data_struct
,this->payload_infos
[i
]->ecoding_rules
,this->payload_infos
[i
]->encoding_rules_count
,data
));
460 return NOT_SUPPORTED
;
464 * Implementation of generator_t's destroy function
466 static status_t
destroy(private_generator_t
*this)
473 allocator_free(this);
478 * Described in header
480 generator_t
* generator_create(payload_info_t
** payload_infos
)
482 private_generator_t
*this;
484 if (payload_infos
== NULL
)
489 this = allocator_alloc_thing(private_generator_t
);
495 /* initiate public functions */
496 this->public.generate_payload
= (status_t(*)(generator_t
*, payload_type_t
, void *, chunk_t
*)) generate_payload
;
497 this->public.destroy
= (status_t(*)(generator_t
*)) destroy
;
499 /* initiate private functions */
500 this->generate
= generate
;
501 this->generate_u_int_type
= generate_u_int_type
;
503 /* initiate private variables */
504 this->payload_infos
= payload_infos
;
506 return &(this->public);