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_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 size_t free_bits
= ((this->roof_position
- this->out_position
) * 8) - this->current_bit
;
94 while (free_bits
< bits
)
96 size_t old_buffer_size
= ((this->roof_position
) - ( this->buffer
));
97 size_t new_buffer_size
= old_buffer_size
+ GENERATOR_DATA_BUFFER_INCREASE_VALUE
;
98 size_t out_position_offset
= ((this->out_position
) - (this->buffer
));
101 new_buffer
= allocator_realloc(this->buffer
,new_buffer_size
);
102 if (new_buffer
== NULL
)
107 this->buffer
= new_buffer
;
109 this->out_position
= (this->buffer
+ out_position_offset
);
110 this->roof_position
= (this->buffer
+ new_buffer_size
);
116 static status_t
generator_infos_write_chunk (generator_infos_t
*this,chunk_t
*data
)
118 size_t data_length
= this->out_position
- this->buffer
;
119 if (this->current_bit
> 0)
121 data
->ptr
= allocator_alloc(data_length
);
122 if (data
->ptr
== NULL
)
127 memcpy(data
->ptr
,this->buffer
,data_length
);
128 data
->len
= data_length
;
133 static status_t
generator_infos_destroy (generator_infos_t
*this)
139 allocator_free(this->buffer
);
140 allocator_free(this);
145 * Creates a generator_infos_t-object holding necessary informations
146 * for generating (buffer, data_struct, etc)
148 * @param data_struct where to read the data out
150 generator_infos_t
* generator_infos_create(void *data_struct
)
152 generator_infos_t
*this = allocator_alloc_thing(generator_infos_t
);
160 this->destroy
= generator_infos_destroy
;
161 this->make_space_available
= generator_info_make_space_available
;
162 this->write_chunk
= generator_infos_write_chunk
;
164 /* allocate memory for buffer */
165 this->buffer
= allocator_alloc(GENERATOR_DATA_BUFFER_SIZE
);
166 if (this->buffer
== NULL
)
168 allocator_free(this);
172 /* set private data */
173 this->out_position
= this->buffer
;
174 this->roof_position
= this->buffer
+ GENERATOR_DATA_BUFFER_SIZE
;
175 this->data_struct
= data_struct
;
176 this->current_bit
= 0;
183 * Private data of a generator_t object
185 typedef struct private_generator_s private_generator_t
;
187 struct private_generator_s
{
189 * Public part of a generator object
193 /* private functions and fields */
196 * Generates a chunk_t with specific encoding rules
198 * items are bytewhise written
200 * @param this private_generator_t-object
201 * @param data_struct data_struct to read data from
202 * @param encoding_rules pointer to first encoding_rule of encoding rules array
203 * @param encoding_rules_count number of encoding rules in encoding rules array
204 * @param data pointer to chunk where to write the data in
206 * @return SUCCESS if succeeded,
207 * OUT_OF_RES if out of ressources
209 status_t (*generate
) (private_generator_t
*this,void * data_struct
,encoding_rule_t
*encoding_rules
, size_t encoding_rules_count
, chunk_t
*data
);
214 status_t (*generate_u_int_type
) (private_generator_t
*this,encoding_type_t int_type
,u_int32_t offset
, generator_infos_t
*generator_infos
);
217 * Pointer to the payload informations needed to automatic
218 * generate a specific payload type
220 payload_info_t
**payload_infos
;
224 * implements private_generator_t's double_buffer function
226 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
)
228 size_t number_of_bits
= 0;
254 status
= generator_infos
->make_space_available(generator_infos
,number_of_bits
);
256 if (status
!= SUCCESS
)
261 /* process 4 byte integer special */
262 if (number_of_bits
== 4)
264 if (generator_infos
->current_bit
== 0)
266 *(generator_infos
->out_position
) = *((u_int8_t
*)(generator_infos
->data_struct
+ offset
)) << 4;
267 generator_infos
->current_bit
= 4;
269 else if (generator_infos
->current_bit
== 4)
271 generator_infos
->out_position
++;
272 generator_infos
->current_bit
= 0;
277 /* 4 Bit integers must have a 4 bit alignment */
285 * implements private_generator_t's generate function
287 static status_t
generate (private_generator_t
*this,void * data_struct
,encoding_rule_t
*encoding_rules
, size_t encoding_rules_count
, chunk_t
*data
)
293 generator_infos_t
*infos
= generator_infos_create(data_struct
);
300 for (i
= 0; i
< encoding_rules_count
;i
++)
303 switch (encoding_rules
[i
].type
)
310 status
= this->generate_u_int_type(this,encoding_rules
[i
].type
,encoding_rules
[i
].offset
,infos
);
320 if (status
!= SUCCESS
)
322 infos
->destroy(infos
);
328 status
= infos
->write_chunk(infos
,data
);
329 infos
->destroy(infos
);
333 static status_t
generate_payload (private_generator_t
*this,payload_type_t payload_type
,void * data_struct
, chunk_t
*data
)
337 /* check every payload info for specific type */
338 for (i
= 0; this->payload_infos
[i
] != NULL
; i
++)
340 if (this->payload_infos
[i
]->payload_type
== payload_type
)
342 /* found payload informations, generating is done in private function generate() */
343 return (this->generate(this, data_struct
,this->payload_infos
[i
]->ecoding_rules
,this->payload_infos
[i
]->encoding_rules_count
,data
));
346 return NOT_SUPPORTED
;
350 * Implementation of generator_t's destroy function
352 static status_t
destroy(private_generator_t
*this)
359 allocator_free(this);
364 * Described in header
366 generator_t
* generator_create(payload_info_t
** payload_infos
)
368 private_generator_t
*this;
370 if (payload_infos
== NULL
)
375 this = allocator_alloc_thing(private_generator_t
);
381 /* initiate public functions */
382 this->public.generate_payload
= (status_t(*)(generator_t
*, payload_type_t
, void *, chunk_t
*)) generate_payload
;
383 this->public.destroy
= (status_t(*)(generator_t
*)) destroy
;
385 /* initiate private functions */
386 this->generate
= generate
;
387 this->generate_u_int_type
= generate_u_int_type
;
389 /* initiate private variables */
390 this->payload_infos
= payload_infos
;
392 return &(this->public);