generator now has its generator_context which is used to generate more
[strongswan.git] / Source / charon / generator.c
1 /**
2 * @file generator.c
3 *
4 * @brief Generic generator class used to generate IKEv2-header and payloads.
5 *
6 */
7
8 /*
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 *
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>.
16 *
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
20 * for more details.
21 */
22
23 #include <stdlib.h>
24 #include <string.h>
25 #include <arpa/inet.h>
26 #include <stdio.h>
27
28 #include "allocator.h"
29 #include "types.h"
30 #include "generator.h"
31
32
33 typedef struct private_generator_context_s private_generator_context_t;
34
35 struct private_generator_context_s{
36 /**
37 * Public part of the context
38 */
39 generator_context_t public;
40
41 /**
42 * Buffer used to generate the data into.
43 */
44 u_int8_t *buffer;
45
46 /**
47 * Current write position in buffer (one byte aligned).
48 */
49 u_int8_t *out_position;
50
51 /**
52 * Position of last byte in buffer.
53 */
54 u_int8_t *roof_position;
55
56 /**
57 * Current bit writing to in current byte (between 0 and 7).
58 */
59 size_t current_bit;
60
61 /**
62 * Associated data struct to read informations from.
63 */
64 void * data_struct;
65
66 /**
67 * Writes the current buffer content into a chunk_t
68 *
69 * Memory of specific chunk_t gets allocated.
70 *
71 * @param generator_infos_t calling generator_infos_t object
72 * @param data pointer of chunk_t to write to
73 * @return
74 * - SUCCESSFUL if succeeded
75 * - OUT_OF_RES otherwise
76 */
77 status_t (*write_chunk) (private_generator_context_t *this,chunk_t *data);
78
79
80 /**
81 * Makes sure enough space is available in buffer to store amount of bits.
82 *
83 * If buffer is to small to hold the specific amount of bits it
84 * is increased using reallocation function of allocator.
85 *
86 * @param generator_infos_t calling generator_infos_t object
87 * @param bits number of bits to make available in buffer
88 * @return
89 * - SUCCESSFUL if succeeded
90 * - OUT_OF_RES otherwise
91 */
92 status_t (*make_space_available) (private_generator_context_t *this,size_t bits);
93
94 /**
95 * Writes a specific amount of byte into the buffer.
96 *
97 * If buffer is to small to hold the specific amount of bytes it
98 * is increased.
99 *
100 * @param generator_infos_t calling generator_infos_t object
101 * @param bytes pointer to bytes to write
102 * @param number_of_bytes number of bytes to write into buffer
103 * @return
104 * - SUCCESSFUL if succeeded
105 * - OUT_OF_RES otherwise
106 */
107 status_t (*write_bytes_to_buffer) (private_generator_context_t *this,void * bytes,size_t number_of_bytes);
108
109
110 };
111
112 /**
113 * Implements generator_infos_t's increase_buffer function.
114 * See #generator_infos_s.increase_buffer.
115 */
116 static status_t generator_context_make_space_available (private_generator_context_t *this, size_t bits)
117 {
118 while ((((this->roof_position - this->out_position) * 8) - this->current_bit) < bits)
119 {
120 size_t old_buffer_size = ((this->roof_position) - ( this->buffer));
121 size_t new_buffer_size = old_buffer_size + GENERATOR_DATA_BUFFER_INCREASE_VALUE;
122 size_t out_position_offset = ((this->out_position) - (this->buffer));
123 u_int8_t *new_buffer;
124
125 new_buffer = allocator_realloc(this->buffer,new_buffer_size);
126 if (new_buffer == NULL)
127 {
128 return OUT_OF_RES;
129 }
130
131 this->buffer = new_buffer;
132
133 this->out_position = (this->buffer + out_position_offset);
134 this->roof_position = (this->buffer + new_buffer_size);
135
136 }
137
138 return SUCCESS;
139 }
140
141 /**
142 * Implements generator_infos_t's write_bytes_to_buffer function.
143 * See #generator_infos_s.write_bytes_to_buffer.
144 */
145 static status_t generator_context_write_bytes_to_buffer (private_generator_context_t *this,void * bytes,size_t number_of_bytes)
146 {
147 u_int8_t *read_position = (u_int8_t *) bytes;
148 int i;
149 status_t status;
150
151 status = this->make_space_available(this,number_of_bytes * 8);
152
153 if (status != SUCCESS)
154 {
155 return status;
156 }
157
158 for (i = 0; i < number_of_bytes; i++)
159 {
160 *(this->out_position) = *(read_position);
161 read_position++;
162 this->out_position++;
163 }
164 return status;
165 }
166
167 /**
168 * Implements generator_infos_t's write_chunk function.
169 * See #generator_infos_s.write_chunk.
170 */
171 static status_t generator_context_write_chunk (private_generator_context_t *this,chunk_t *data)
172 {
173 size_t data_length = this->out_position - this->buffer;
174
175 if (this->current_bit > 0)
176 data_length++;
177 data->ptr = allocator_alloc(data_length);
178 if (data->ptr == NULL)
179 {
180 data->len = 0;
181 return OUT_OF_RES;
182 }
183 memcpy(data->ptr,this->buffer,data_length);
184 data->len = data_length;
185 return SUCCESS;
186 }
187
188
189 /**
190 * Implements generator_infos_t's destroy function.
191 * See #generator_infos_s.destroy.
192 */
193 static status_t generator_context_destroy (private_generator_context_t *this)
194 {
195 allocator_free(this->buffer);
196 allocator_free(this);
197 return SUCCESS;
198 }
199
200 /*
201 * Described in header
202 */
203 static generator_context_t * generator_context_create(generator_t *generator)
204 {
205 private_generator_context_t *this = allocator_alloc_thing(private_generator_context_t);
206
207 if (this == NULL)
208 {
209 return NULL;
210 }
211
212 /* object methods */
213 this->public.destroy = (status_t (*) (generator_context_t *this))generator_context_destroy;
214 this->make_space_available = generator_context_make_space_available;
215 this->write_chunk = generator_context_write_chunk;
216 this->write_bytes_to_buffer = generator_context_write_bytes_to_buffer;
217
218 /* allocate memory for buffer */
219 this->buffer = allocator_alloc(GENERATOR_DATA_BUFFER_SIZE);
220 if (this->buffer == NULL)
221 {
222 allocator_free(this);
223 return NULL;
224 }
225
226 /* set private data */
227 this->out_position = this->buffer;
228 this->roof_position = this->buffer + GENERATOR_DATA_BUFFER_SIZE;
229 this->data_struct = NULL;
230 this->current_bit = 0;
231 return &(this->public);
232 }
233
234
235 /**
236 * Private part of a generator_t object
237 */
238 typedef struct private_generator_s private_generator_t;
239
240 struct private_generator_s {
241 /**
242 * Public part of a generator_t object
243 */
244 generator_t public;
245
246 /* private functions and fields */
247
248 /**
249 * Generates a chunk_t with specific encoding rules.
250 *
251 * Iems are bytewhise written.
252 *
253 * @param this private_generator_t object
254 * @param data_struct data_struct to read data from
255 * @param encoding_rules pointer to first encoding_rule
256 * of encoding rules array
257 * @param encoding_rules_count number of encoding rules
258 * in encoding rules array
259 * @param data pointer to chunk_t where to write the data in
260 *
261 * @return - SUCCESS if succeeded
262 * - OUT_OF_RES if out of ressources
263 */
264 status_t (*generate) (private_generator_t *this,void * data_struct,encoding_rule_t *encoding_rules, size_t encoding_rules_count, private_generator_context_t *generator_context);
265
266 /**
267 * Generates a U_INT-Field type
268 *
269 * @param this private_generator_t object
270 * @param int_type type of U_INT field (U_INT_4, U_INT_8, etc.)
271 * @param offset offset of value in data struct
272 * @param generator_contexts generator_contexts_t object where the context is written or read from
273 * @return - SUCCESS if succeeded
274 * - OUT_OF_RES if out of ressources
275 */
276 status_t (*generate_u_int_type) (private_generator_t *this,encoding_type_t int_type,u_int32_t offset, private_generator_context_t *generator_context);
277
278 /**
279 * Generates a RESERVED BIT field or a RESERVED BYTE field
280 *
281 * @param this private_generator_t object
282 * @param generator_contexts generator_contexts_t object where the context is written or read from
283 * @param bits number of bits to generate
284 * @return - SUCCESS if succeeded
285 * - OUT_OF_RES if out of ressources
286 * - FAILED if bit count not supported
287 */
288 status_t (*generate_reserved_field) (private_generator_t *this,private_generator_context_t *generator_context,int bits);
289
290 /**
291 * Generates a FLAG field
292 *
293 * @param this private_generator_t object
294 * @param generator_contexts generator_contexts_t object where the context is written or read from
295 * @param offset offset of flag value in data struct
296 * @return - SUCCESS if succeeded
297 * - OUT_OF_RES if out of ressources
298 */
299 status_t (*generate_flag) (private_generator_t *this,private_generator_context_t *generator_context,u_int32_t offset);
300
301 /**
302 * Pointer to the payload informations needed to automatic
303 * generate a specific payload type
304 */
305 payload_info_t **payload_infos;
306 };
307
308 /**
309 * Implements private_generator_t's generate_u_int_type function.
310 * See #private_generator_s.generate_u_int_type.
311 */
312 static status_t generate_u_int_type (private_generator_t *this,encoding_type_t int_type,u_int32_t offset,private_generator_context_t *generator_context)
313 {
314 size_t number_of_bits = 0;
315 status_t status;
316
317
318 switch (int_type)
319 {
320 case U_INT_4:
321 number_of_bits = 4;
322 break;
323 case U_INT_8:
324 number_of_bits = 8;
325 break;
326 case U_INT_16:
327 number_of_bits = 16;
328 break;
329 case U_INT_32:
330 number_of_bits = 32;
331 break;
332 case U_INT_64:
333 number_of_bits = 64;
334 break;
335 default:
336 return FAILED;
337 }
338 if (((number_of_bits % 8) == 0) && (generator_context->current_bit != 0))
339 {
340 /* current bit has to be zero for values greater then 4 bits */
341 return FAILED;
342 }
343
344 status = generator_context->make_space_available(generator_context,number_of_bits);
345
346 if (status != SUCCESS)
347 {
348 return status;
349 }
350
351 switch (int_type)
352 {
353 case U_INT_4:
354 {
355 if (generator_context->current_bit == 0)
356 {
357 u_int8_t high_val = *((u_int8_t *)(generator_context->data_struct + offset)) << 4;
358 u_int8_t low_val = *(generator_context->out_position) & 0x0F;
359
360 *(generator_context->out_position) = high_val | low_val;
361 /* write position is not changed, just bit position is moved */
362 generator_context->current_bit = 4;
363 }
364 else if (generator_context->current_bit == 4)
365 {
366 u_int high_val = *(generator_context->out_position) & 0xF0;
367 u_int low_val = *((u_int8_t *)(generator_context->data_struct + offset)) & 0x0F;
368 *(generator_context->out_position) = high_val | low_val;
369 generator_context->out_position++;
370 generator_context->current_bit = 0;
371
372 }
373 else
374 {
375 /* 4 Bit integers must have a 4 bit alignment */
376 return FAILED;
377 };
378 break;
379 }
380
381 case U_INT_8:
382 {
383 *generator_context->out_position = *((u_int8_t *)(generator_context->data_struct + offset));
384 generator_context->out_position++;
385 break;
386
387 }
388 case U_INT_16:
389 {
390 u_int16_t int16_val = htons(*((u_int16_t*)(generator_context->data_struct + offset)));
391 generator_context->write_bytes_to_buffer(generator_context,&int16_val,sizeof(u_int16_t));
392
393 break;
394 }
395 case U_INT_32:
396 {
397 u_int32_t int32_val = htonl(*((u_int32_t*)(generator_context->data_struct + offset)));
398 generator_context->write_bytes_to_buffer(generator_context,&int32_val,sizeof(u_int32_t));
399 break;
400 }
401 case U_INT_64:
402 {
403 u_int32_t int32_val_low = htonl(*((u_int32_t*)(generator_context->data_struct + offset)));
404 u_int32_t int32_val_high = htonl(*((u_int32_t*)(generator_context->data_struct + offset) + 1));
405 generator_context->write_bytes_to_buffer(generator_context,&int32_val_high,sizeof(u_int32_t));
406 generator_context->write_bytes_to_buffer(generator_context,&int32_val_low,sizeof(u_int32_t));
407 break;
408 }
409
410 default:
411 return FAILED;
412
413 }
414
415 return SUCCESS;
416 }
417
418 static status_t generate_reserved_field (private_generator_t *this,private_generator_context_t *generator_context,int bits)
419 {
420 status_t status;
421
422 if ((bits != 1) && (bits != 8))
423 {
424 return FAILED;
425 }
426 status = generator_context->make_space_available(generator_context,bits);
427 if (status != SUCCESS)
428 {
429 return status;
430 }
431
432 if (bits == 1)
433 {
434 u_int8_t reserved_bit = ~(1 << (7 - generator_context->current_bit));
435
436 *(generator_context->out_position) = *(generator_context->out_position) & reserved_bit;
437 generator_context->current_bit++;
438 if (generator_context->current_bit >= 8)
439 {
440 generator_context->current_bit = generator_context->current_bit % 8;
441 generator_context->out_position++;
442 }
443 }
444 else
445 {
446 /* one byte */
447 if (generator_context->current_bit > 0)
448 {
449 return FAILED;
450 }
451 *(generator_context->out_position) = 0x00;
452 generator_context->out_position++;
453 }
454
455 return SUCCESS;
456
457
458 }
459
460 static status_t generate_flag (private_generator_t *this,private_generator_context_t *generator_context,u_int32_t offset)
461 {
462 status_t status;
463 u_int8_t flag_value = (*((bool *) (generator_context->data_struct + offset))) ? 1 : 0;
464 u_int8_t flag = (flag_value << (7 - generator_context->current_bit));
465
466 status = generator_context->make_space_available(generator_context,1);
467 if (status != SUCCESS)
468 {
469 return status;
470 }
471
472 *(generator_context->out_position) = *(generator_context->out_position) | flag;
473
474 generator_context->current_bit++;
475 if (generator_context->current_bit >= 8)
476 {
477 generator_context->current_bit = generator_context->current_bit % 8;
478 generator_context->out_position++;
479 }
480 return SUCCESS;
481 }
482
483 /**
484 * Implements private_generator_t's generate function.
485 * See #private_generator_s.generate.
486 */
487 static status_t generate (private_generator_t *this,void * data_struct,encoding_rule_t *encoding_rules, size_t encoding_rules_count, private_generator_context_t *generator_context)
488 {
489 int i;
490 status_t status;
491
492 if (generator_context == NULL)
493 {
494 return OUT_OF_RES;
495 }
496
497 for (i = 0; i < encoding_rules_count;i++)
498 {
499 status = SUCCESS;
500 switch (encoding_rules[i].type)
501 {
502 /* all u int values are generated in generate_u_int_type */
503 case U_INT_4:
504 case U_INT_8:
505 case U_INT_16:
506 case U_INT_32:
507 case U_INT_64:
508 status = this->generate_u_int_type(this,encoding_rules[i].type,encoding_rules[i].offset,generator_context);
509 break;
510 case RESERVED_BIT:
511 {
512 status = this->generate_reserved_field(this,generator_context,1);
513
514 break;
515 }
516 case RESERVED_BYTE:
517 {
518 status = this->generate_reserved_field(this,generator_context,8);
519 break;
520 }
521 case FLAG:
522 {
523 status = this->generate_flag(this,generator_context,encoding_rules[i].offset);
524 break;
525 }
526 case LENGTH:
527 /* length is generated like an U_INT_32 */
528 status = this->generate_u_int_type(this,U_INT_32,encoding_rules[i].offset,generator_context);
529 break;
530 case SPI_SIZE:
531 /* currently not implemented */
532 default:
533 break;
534 }
535 if (status != SUCCESS)
536 {
537 generator_context->public.destroy(&(generator_context->public));
538 return status;
539 }
540 }
541
542 // infos->destroy(infos);
543 return status;
544 }
545
546 /**
547 * Implements generator_t's generate_payload function.
548 * See #generator_s.generate_payload.
549 */
550 static status_t generate_payload (private_generator_t *this,payload_type_t payload_type,void * data_struct, generator_context_t *generator_context)
551 {
552 int i;
553
554 private_generator_context_t *private_generator_context = (private_generator_context_t *) generator_context;
555
556 private_generator_context->data_struct = data_struct;
557
558 /* check every payload info for specific type */
559 for (i = 0; this->payload_infos[i] != NULL; i++)
560 {
561 if (this->payload_infos[i]->payload_type == payload_type)
562 {
563 /* found payload informations, generating is done in private function generate() */
564 return (this->generate(this, data_struct,this->payload_infos[i]->ecoding_rules,this->payload_infos[i]->encoding_rules_count,private_generator_context));
565 }
566 }
567 return NOT_SUPPORTED;
568 }
569
570 status_t write_to_chunk (private_generator_t *this,private_generator_context_t *generator_context, chunk_t *data)
571 {
572 return generator_context->write_chunk(generator_context,data);
573 }
574
575 /**
576 * Implements generator_t's destroy function.
577 * See #generator_s.destroy.
578 */
579 static status_t destroy(private_generator_t *this)
580 {
581 allocator_free(this);
582 return SUCCESS;
583 }
584
585 /*
586 * Described in header
587 */
588 generator_t * generator_create(payload_info_t ** payload_infos)
589 {
590 private_generator_t *this;
591
592 if (payload_infos == NULL)
593 {
594 return NULL;
595 }
596
597 this = allocator_alloc_thing(private_generator_t);
598 if (this == NULL)
599 {
600 return NULL;
601 }
602
603 /* initiate public functions */
604 this->public.create_context = (generator_context_t * (*) (generator_t *)) generator_context_create;
605 this->public.generate_payload = (status_t(*)(generator_t*, payload_type_t, void *, generator_context_t *)) generate_payload;
606 this->public.destroy = (status_t(*)(generator_t*)) destroy;
607 this->public.write_to_chunk = (status_t (*) (generator_t *,generator_context_t *, chunk_t *)) write_to_chunk;
608 /* initiate private functions */
609 this->generate = generate;
610 this->generate_u_int_type = generate_u_int_type;
611 this->generate_reserved_field = generate_reserved_field;
612 this->generate_flag = generate_flag;
613
614 /* initiate private variables */
615 this->payload_infos = payload_infos;
616
617 return &(this->public);
618 }