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