- wrote payload sa_payload
[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 "utils/linked_list.h"
34 #include "utils/logger_manager.h"
35 #include "payloads/payload.h"
36 #include "payloads/proposal_substructure.h"
37 #include "payloads/transform_substructure.h"
38 #include "payloads/sa_payload.h"
39 #include "payloads/ke_payload.h"
40
41 extern logger_manager_t *global_logger_manager;
42
43 /**
44 * Private part of a generator_t object
45 */
46 typedef struct private_generator_s private_generator_t;
47
48 struct private_generator_s {
49 /**
50 * Public part of a generator_t object
51 */
52 generator_t public;
53
54 /* private functions and fields */
55
56
57 /**
58 * Generates a U_INT-Field type and writes it to buffer.
59 *
60 * @param this private_generator_t object
61 * @param int_type type of U_INT field (U_INT_4, U_INT_8, etc.)
62 * ATTRIBUTE_TYPE is also generated in this function
63 * @param offset offset of value in data struct
64 * @param generator_contexts generator_contexts_t object where the context is written or read from
65 * @return - SUCCESS if succeeded
66 * - OUT_OF_RES if out of ressources
67 */
68 status_t (*generate_u_int_type) (private_generator_t *this,encoding_type_t int_type,u_int32_t offset);
69
70 /**
71 * Get size of current buffer in bytes.
72 *
73 * @param this private_generator_t object
74 * @return Size of buffer in bytes
75 */
76 size_t (*get_current_buffer_size) (private_generator_t *this);
77
78 /**
79 * Get free space of current buffer in bytes.
80 *
81 * @param this private_generator_t object
82 * @return space in buffer in bytes
83 */
84 size_t (*get_current_buffer_space) (private_generator_t *this);
85
86 /**
87 * Get length of data in buffer (in bytes).
88 *
89 * @param this private_generator_t object
90 * @return length of data in bytes
91 */
92 size_t (*get_current_data_length) (private_generator_t *this);
93
94 /**
95 * Get current offset in buffer (in bytes).
96 *
97 * @param this private_generator_t object
98 * @return offset in bytes
99 */
100 u_int32_t (*get_current_buffer_offset) (private_generator_t *this);
101
102 /**
103 * Generates a RESERVED BIT field or a RESERVED BYTE field and writes
104 * it to the buffer.
105 *
106 * @param this private_generator_t object
107 * @param generator_contexts generator_contexts_t object where the context is written or read from
108 * @param bits number of bits to generate
109 * @return - SUCCESS if succeeded
110 * - OUT_OF_RES if out of ressources
111 * - FAILED if bit count not supported
112 */
113 status_t (*generate_reserved_field) (private_generator_t *this,int bits);
114
115 /**
116 * Generates a FLAG field
117 *
118 * @param this private_generator_t object
119 * @param generator_contexts generator_contexts_t object where the context is written or read from
120 * @param offset offset of flag value in data struct
121 * @return - SUCCESS if succeeded
122 * - OUT_OF_RES if out of ressources
123 */
124 status_t (*generate_flag) (private_generator_t *this,u_int32_t offset);
125
126 /**
127 * Writes the current buffer content into a chunk_t
128 *
129 * Memory of specific chunk_t gets allocated.
130 *
131 * @param this calling private_generator_t object
132 * @param data pointer of chunk_t to write to
133 * @return
134 * - SUCCESSFUL if succeeded
135 * - OUT_OF_RES otherwise
136 */
137 status_t (*write_chunk) (private_generator_t *this,chunk_t *data);
138
139 /**
140 * Generates a bytestream from a chunk_t
141 *
142 * @param this private_generator_t object
143 * @param offset offset of chunk_t value in data struct
144 * @return - SUCCESS if succeeded
145 * - OUT_OF_RES if out of ressources
146 */
147 status_t (*generate_from_chunk) (private_generator_t *this,u_int32_t offset);
148
149 /**
150 * Makes sure enough space is available in buffer to store amount of bits.
151 *
152 * If buffer is to small to hold the specific amount of bits it
153 * is increased using reallocation function of allocator.
154 *
155 * @param this calling private_generator_t object
156 * @param bits number of bits to make available in buffer
157 * @return
158 * - SUCCESSFUL if succeeded
159 * - OUT_OF_RES otherwise
160 */
161 status_t (*make_space_available) (private_generator_t *this,size_t bits);
162
163 /**
164 * Writes a specific amount of byte into the buffer.
165 *
166 * If buffer is to small to hold the specific amount of bytes it
167 * is increased.
168 *
169 * @param this calling private_generator_t object
170 * @param bytes pointer to bytes to write
171 * @param number_of_bytes number of bytes to write into buffer
172 * @return
173 * - SUCCESSFUL if succeeded
174 * - OUT_OF_RES otherwise
175 */
176 status_t (*write_bytes_to_buffer) (private_generator_t *this,void * bytes,size_t number_of_bytes);
177
178
179 /**
180 * Writes a specific amount of byte into the buffer at a specific offset.
181 *
182 * @warning buffer size is not check to hold the data if offset is to large.
183 *
184 * @param this calling private_generator_t object
185 * @param bytes pointer to bytes to write
186 * @param number_of_bytes number of bytes to write into buffer
187 * @param offset offset to write the data into
188 * @return
189 * - SUCCESSFUL if succeeded
190 * - OUT_OF_RES otherwise
191 */
192 status_t (*write_bytes_to_buffer_at_offset) (private_generator_t *this,void * bytes,size_t number_of_bytes,u_int32_t offset);
193
194 /**
195 * Buffer used to generate the data into.
196 */
197 u_int8_t *buffer;
198
199 /**
200 * Current write position in buffer (one byte aligned).
201 */
202 u_int8_t *out_position;
203
204 /**
205 * Position of last byte in buffer.
206 */
207 u_int8_t *roof_position;
208
209 /**
210 * Current bit writing to in current byte (between 0 and 7).
211 */
212 size_t current_bit;
213
214 /**
215 * Associated data struct to read informations from.
216 */
217 void * data_struct;
218
219 /*
220 * Last payload length position offset in the buffer
221 */
222 u_int32_t last_payload_length_position_offset;
223
224 /**
225 * Offset of the header length field in the buffer
226 */
227 u_int32_t header_length_position_offset;
228
229 /**
230 * Last SPI size
231 */
232 u_int8_t last_spi_size;
233
234 /*
235 * Attribute format of the last generated transform attribute
236 *
237 * Used to check if a variable value field is used or not for
238 * the transform attribute value.
239 */
240 bool attribute_format;
241
242 /*
243 * Depending on the value of attribute_format this field is used
244 * to hold the length of the transform attribute in bytes
245 */
246 u_int16_t attribute_length;
247
248 /**
249 * Associated Logger
250 */
251 logger_t *logger;
252 };
253
254 /**
255 * Implements private_generator_t's get_current_buffer_size function.
256 * See #private_generator_s.get_current_buffer_size.
257 */
258 static size_t get_current_buffer_size (private_generator_t *this)
259 {
260 return ((this->roof_position) - (this->buffer));
261 }
262
263 /**
264 * Implements private_generator_t's get_current_buffer_space function.
265 * See #private_generator_s.get_current_buffer_space.
266 */
267 static size_t get_current_buffer_space (private_generator_t *this)
268 {
269 /* we know, one byte more */
270 size_t space = (this->roof_position) - (this->out_position);
271 if (this->current_bit == 0)
272 {
273 space++;
274 }
275 return (space);
276 }
277
278 /**
279 * Implements private_generator_t's get_current_buffer_space function.
280 * See #private_generator_s.get_current_buffer_space.
281 */
282 static size_t get_current_data_length (private_generator_t *this)
283 {
284 return (this->out_position - this->buffer);
285 }
286
287 /**
288 * Implements private_generator_t's get_current_buffer_offset function.
289 * See #private_generator_s.get_current_buffer_offset.
290 */
291 static u_int32_t get_current_buffer_offset (private_generator_t *this)
292 {
293 return (this->out_position - this->buffer);
294 }
295
296
297 /**
298 * Implements private_generator_t's generate_u_int_type function.
299 * See #private_generator_s.generate_u_int_type.
300 */
301 static status_t generate_u_int_type (private_generator_t *this,encoding_type_t int_type,u_int32_t offset)
302 {
303 size_t number_of_bits = 0;
304 status_t status;
305
306 /* find out number of bits of each U_INT type to check for enough space
307 in buffer */
308 switch (int_type)
309 {
310 case U_INT_4:
311 number_of_bits = 4;
312 break;
313 case U_INT_8:
314 number_of_bits = 8;
315 break;
316 case U_INT_16:
317 number_of_bits = 16;
318 break;
319 case U_INT_32:
320 number_of_bits = 32;
321 break;
322 case U_INT_64:
323 number_of_bits = 64;
324 break;
325 case ATTRIBUTE_TYPE:
326 number_of_bits = 15;
327 break;
328 default:
329 return FAILED;
330 }
331 /* U_INT Types of multiple then 8 bits must be aligned */
332 if (((number_of_bits % 8) == 0) && (this->current_bit != 0))
333 {
334 this->logger->log(this->logger,CONTROL_MORE,"U_INT Type %s is not 8 Bit aligned", mapping_find(encoding_type_t_mappings,int_type));
335 /* current bit has to be zero for values multiple of 8 bits */
336 return FAILED;
337 }
338
339 /* make sure enough space is available in buffer */
340 status = this->make_space_available(this,number_of_bits);
341 if (status != SUCCESS)
342 {
343 return status;
344 }
345 /* now handle each u int type differently */
346 switch (int_type)
347 {
348 case U_INT_4:
349 {
350 if (this->current_bit == 0)
351 {
352 /* highval of current byte in buffer has to be set to the new value*/
353 u_int8_t high_val = *((u_int8_t *)(this->data_struct + offset)) << 4;
354 /* lowval in buffer is not changed */
355 u_int8_t low_val = *(this->out_position) & 0x0F;
356 /* highval is set, low_val is not changed */
357 *(this->out_position) = high_val | low_val;
358 /* write position is not changed, just bit position is moved */
359 this->current_bit = 4;
360 }
361 else if (this->current_bit == 4)
362 {
363 /* highval in buffer is not changed */
364 u_int high_val = *(this->out_position) & 0xF0;
365 /* lowval of current byte in buffer has to be set to the new value*/
366 u_int low_val = *((u_int8_t *)(this->data_struct + offset)) & 0x0F;
367 *(this->out_position) = high_val | low_val;
368 this->out_position++;
369 this->current_bit = 0;
370
371 }
372 else
373 {
374 this->logger->log(this->logger,CONTROL_MORE,"U_INT_4 Type is not 4 Bit aligned");
375 /* 4 Bit integers must have a 4 bit alignment */
376 return FAILED;
377 };
378 break;
379 }
380 case U_INT_8:
381 {
382 /* 8 bit values are written as they are */
383 *this->out_position = *((u_int8_t *)(this->data_struct + offset));
384 this->out_position++;
385 break;
386
387 }
388 case ATTRIBUTE_TYPE:
389 {
390 /* attribute type must not change first bit uf current byte ! */
391 if (this->current_bit != 1)
392 {
393 this->logger->log(this->logger,CONTROL_MORE,"ATTRIBUTE FORMAT flag is not set");
394 /* first bit has to be set! */
395 return FAILED;
396 }
397 /* get value of attribute format flag */
398 u_int8_t attribute_format_flag = *(this->out_position) & 0x80;
399 /* get attribute type value as 16 bit integer*/
400 u_int16_t int16_val = htons(*((u_int16_t*)(this->data_struct + offset)));
401 /* last bit must be unset */
402 int16_val = int16_val & 0xFF7F;
403
404 int16_val = int16_val | attribute_format_flag;
405 /* write bytes to buffer (set bit is overwritten)*/
406 this->write_bytes_to_buffer(this,&int16_val,sizeof(u_int16_t));
407 this->current_bit = 0;
408 break;
409
410 }
411 case U_INT_16:
412 {
413 u_int16_t int16_val = htons(*((u_int16_t*)(this->data_struct + offset)));
414 this->write_bytes_to_buffer(this,&int16_val,sizeof(u_int16_t));
415 break;
416 }
417 case U_INT_32:
418 {
419 u_int32_t int32_val = htonl(*((u_int32_t*)(this->data_struct + offset)));
420 this->write_bytes_to_buffer(this,&int32_val,sizeof(u_int32_t));
421 break;
422 }
423 case U_INT_64:
424 {
425 /* 64 bit integers are written as two 32 bit integers */
426 u_int32_t int32_val_low = htonl(*((u_int32_t*)(this->data_struct + offset)));
427 u_int32_t int32_val_high = htonl(*((u_int32_t*)(this->data_struct + offset) + 1));
428 /* TODO add support for big endian machines */
429 this->write_bytes_to_buffer(this,&int32_val_high,sizeof(u_int32_t));
430 this->write_bytes_to_buffer(this,&int32_val_low,sizeof(u_int32_t));
431 break;
432 }
433
434 default:
435 this->logger->log(this->logger,CONTROL_MORE,"U_INT Type %s is not supported", mapping_find(encoding_type_t_mappings,int_type));
436 return FAILED;
437 }
438 return SUCCESS;
439 }
440
441 /**
442 * Implements private_generator_t's generate_reserved_field function.
443 * See #private_generator_s.generate_reserved_field.
444 */
445 static status_t generate_reserved_field (private_generator_t *this,int bits)
446 {
447 status_t status;
448
449 /* only one bit or 8 bit fields are supported */
450 if ((bits != 1) && (bits != 8))
451 {
452 this->logger->log(this->logger,CONTROL_MORE,"Reserved field of %d bits cannot be generated",bits);
453 return FAILED;
454 }
455 /* make sure enough space is available in buffer */
456 status = this->make_space_available(this,bits);
457 if (status != SUCCESS)
458 {
459 return status;
460 }
461
462 if (bits == 1)
463 {
464 /* one bit processing */
465 u_int8_t reserved_bit = ~(1 << (7 - this->current_bit));
466 *(this->out_position) = *(this->out_position) & reserved_bit;
467 this->current_bit++;
468 if (this->current_bit >= 8)
469 {
470 this->current_bit = this->current_bit % 8;
471 this->out_position++;
472 }
473 }
474 else
475 {
476 /* one byte processing*/
477 if (this->current_bit > 0)
478 {
479 this->logger->log(this->logger,CONTROL_MORE,"Reserved field cannot be written cause allignement of current bit is %d",this->current_bit);
480 return FAILED;
481 }
482 *(this->out_position) = 0x00;
483 this->out_position++;
484 }
485
486 return SUCCESS;
487
488
489 }
490
491 /**
492 * Implements private_generator_t's generate_flag function.
493 * See #private_generator_s.generate_flag.
494 */
495 static status_t generate_flag (private_generator_t *this,u_int32_t offset)
496 {
497 status_t status;
498 /* value of current flag */
499 u_int8_t flag_value;
500 /* position of flag in current byte */
501 u_int8_t flag;
502
503 /* if the value in the data_struct is TRUE, flag_value is set to 1, 0 otherwise */
504 flag_value = (*((bool *) (this->data_struct + offset))) ? 1 : 0;
505 /* get flag position */
506 flag = (flag_value << (7 - this->current_bit));
507
508 /* make sure one bit is available in buffer */
509 status = this->make_space_available(this,1);
510 if (status != SUCCESS)
511 {
512 return status;
513 }
514
515 *(this->out_position) = *(this->out_position) | flag;
516
517 this->current_bit++;
518 if (this->current_bit >= 8)
519 {
520 this->current_bit = this->current_bit % 8;
521 this->out_position++;
522 }
523 return SUCCESS;
524 }
525
526 /**
527 * Implements private_generator_t's generate_from_chunk function.
528 * See #private_generator_s.generate_from_chunk.
529 */
530 static status_t generate_from_chunk (private_generator_t *this,u_int32_t offset)
531 {
532 if (this->current_bit != 0)
533 {
534 this->logger->log(this->logger,CONTROL_MORE,"Chunks can only be taken if bits are alligned in buffer");
535 return FAILED;
536 }
537 /* position in buffer */
538 chunk_t *attribute_value = (chunk_t *)(this->data_struct + offset);
539
540 /* use write_bytes_to_buffer function to do the job */
541 return this->write_bytes_to_buffer(this,attribute_value->ptr,attribute_value->len);
542
543 }
544
545 /**
546 * Implements private_generator_t's generator_context_make_space_available function.
547 * See #private_generator_s.generator_context_make_space_available.
548 */
549 static status_t make_space_available (private_generator_t *this, size_t bits)
550 {
551 while (((this->get_current_buffer_space(this) * 8) - this->current_bit) < bits)
552 {
553 /* must increase buffer */
554 u_int8_t *new_buffer;
555 size_t old_buffer_size = this->get_current_buffer_size(this);
556 size_t new_buffer_size = old_buffer_size + GENERATOR_DATA_BUFFER_INCREASE_VALUE;
557 size_t out_position_offset = ((this->out_position) - (this->buffer));
558
559 this->logger->log(this->logger,CONTROL_MORE,"Gen-Buffer is increased from %d to %d byte",old_buffer_size,new_buffer_size);
560
561 /* Reallocate space for new buffer */
562 new_buffer = allocator_realloc(this->buffer,new_buffer_size);
563 if (new_buffer == NULL)
564 {
565 return OUT_OF_RES;
566 }
567
568 this->buffer = new_buffer;
569
570 this->out_position = (this->buffer + out_position_offset);
571 this->roof_position = (this->buffer + new_buffer_size);
572 }
573 return SUCCESS;
574 }
575
576 /**
577 * Implements private_generator_t's write_bytes_to_buffer function.
578 * See #private_generator_s.write_bytes_to_buffer.
579 */
580 static status_t write_bytes_to_buffer (private_generator_t *this,void * bytes,size_t number_of_bytes)
581 {
582 int i;
583 status_t status;
584 u_int8_t *read_position = (u_int8_t *) bytes;
585
586 status = this->make_space_available(this,number_of_bytes * 8);
587 if (status != SUCCESS)
588 {
589 return status;
590 }
591
592 for (i = 0; i < number_of_bytes; i++)
593 {
594 *(this->out_position) = *(read_position);
595 read_position++;
596 this->out_position++;
597 }
598 return status;
599 }
600
601 /**
602 * Implements private_generator_t's write_bytes_to_buffer_at_offset function.
603 * See #private_generator_s.write_bytes_to_buffer_at_offset.
604 */
605 static status_t write_bytes_to_buffer_at_offset (private_generator_t *this,void * bytes,size_t number_of_bytes,u_int32_t offset)
606 {
607 int i;
608 status_t status;
609 u_int8_t *read_position = (u_int8_t *) bytes;
610 u_int8_t *write_position;
611 u_int32_t free_space_after_offset = (this->get_current_buffer_size(this) - offset);
612
613 /* check first if enough space for new data is available */
614 if (number_of_bytes > free_space_after_offset)
615 {
616 status = this->make_space_available(this,(number_of_bytes - free_space_after_offset) * 8);
617 }
618
619 write_position = this->buffer + offset;
620 for (i = 0; i < number_of_bytes; i++)
621 {
622 *(write_position) = *(read_position);
623 read_position++;
624 write_position++;
625 }
626 return SUCCESS;
627 }
628
629 /**
630 * Implements generator_t's write_chunk function.
631 * See #generator_s.write_chunk.
632 */
633 static status_t write_to_chunk (private_generator_t *this,chunk_t *data)
634 {
635 size_t data_length = this->get_current_data_length(this);
636 u_int32_t header_length_field = data_length;
637
638 /* write length into header length field */
639 if (this->header_length_position_offset > 0)
640 {
641 u_int32_t int32_val = htonl(header_length_field);
642 this->write_bytes_to_buffer_at_offset(this,&int32_val,sizeof(u_int32_t),this->header_length_position_offset);
643 }
644
645 if (this->current_bit > 0)
646 data_length++;
647 data->ptr = allocator_alloc(data_length);
648 if (data->ptr == NULL)
649 {
650 data->len = 0;
651 this->logger->log(this->logger,CONTROL_MORE,"OUT OF Ressources to wrote data to chunk!!!!!");
652 return OUT_OF_RES;
653 }
654 memcpy(data->ptr,this->buffer,data_length);
655 data->len = data_length;
656 return SUCCESS;
657 }
658
659 /**
660 * Implements generator_t's generate_payload function.
661 * See #generator_s.generate_payload.
662 */
663 static status_t generate_payload (private_generator_t *this,payload_t *payload)
664 {
665 int i;
666 status_t status;
667 this->data_struct = payload;
668 size_t rule_count;
669 encoding_rule_t *rules;
670 payload_type_t payload_type;
671
672 /* get payload type */
673 payload_type = payload->get_type(payload);
674
675 this->logger->log(this->logger,CONTROL,"Start generating payload of type %s",mapping_find(payload_type_t_mappings,payload_type));
676
677 /* each payload has its own encoding rules */
678 payload->get_encoding_rules(payload,&rules,&rule_count);
679
680 for (i = 0; i < rule_count;i++)
681 {
682 status = SUCCESS;
683 switch (rules[i].type)
684 {
685 /* all u int values and ATTRIBUTE_TYPE are generated in generate_u_int_type */
686 case U_INT_4:
687 case U_INT_8:
688 case U_INT_16:
689 case U_INT_32:
690 case U_INT_64:
691 case ATTRIBUTE_TYPE:
692 {
693 status = this->generate_u_int_type(this,rules[i].type,rules[i].offset);
694 break;
695 }
696 case RESERVED_BIT:
697 {
698 status = this->generate_reserved_field(this,1);
699 break;
700 }
701 case RESERVED_BYTE:
702 {
703 status = this->generate_reserved_field(this,8);
704 break;
705 }
706 case FLAG:
707 {
708 status = this->generate_flag(this,rules[i].offset);
709 break;
710 }
711 case PAYLOAD_LENGTH:
712 {
713 /* position of payload lenght field is temporary stored */
714 this->last_payload_length_position_offset = this->get_current_buffer_offset(this);
715 /* payload length is generated like an U_INT_16 */
716 status = this->generate_u_int_type(this,U_INT_16,rules[i].offset);
717 break;
718 }
719 case HEADER_LENGTH:
720 {
721 /* position of header length field is temporary stored */
722 this->header_length_position_offset = this->get_current_buffer_offset(this);
723 /* header length is generated like an U_INT_32 */
724 status = this->generate_u_int_type(this,U_INT_32,rules[i].offset);
725 break;
726 }
727 case SPI_SIZE:
728 /* spi size is handled as 8 bit unsigned integer */
729 status = this->generate_u_int_type(this,U_INT_8,rules[i].offset);
730 /* last spi size is temporary stored */
731 this->last_spi_size = *((u_int8_t *)(this->data_struct + rules[i].offset));
732 break;
733 case SPI:
734 {
735 /* the SPI value is generated from chunk */
736 status = this->generate_from_chunk(this,rules[i].offset);
737 break;
738 }
739 case KEY_EXCHANGE_DATA:
740 {
741 /* the Key Exchange Data value is generated from chunk */
742 status = this->generate_from_chunk(this,rules[i].offset);
743 if (status != SUCCESS)
744 {
745 this->logger->log(this->logger,CONTROL_MORE,"Could no write key exchange data from chunk");
746 return status;
747 }
748
749 /* before iterative generate the transforms, store the current payload length position */
750 u_int32_t payload_length_position_offset = this->last_payload_length_position_offset;
751 /* Length of KE_PAYLOAD is calculated */
752 u_int16_t length_of_ke_payload = KE_PAYLOAD_HEADER_LENGTH + ((chunk_t *)(this->data_struct + rules[i].offset))->len;
753
754 u_int16_t int16_val = htons(length_of_ke_payload);
755 status = this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),payload_length_position_offset);
756 if (status != SUCCESS)
757 {
758 this->logger->log(this->logger,CONTROL_MORE,"Could no write payload length into buffer");
759 return status;
760 }
761 break;
762 }
763 case PROPOSALS:
764 {
765 /* before iterative generate the transforms, store the current payload length position */
766 u_int32_t payload_length_position_offset = this->last_payload_length_position_offset;
767 /* Length of SA_PAYLOAD is calculated */
768 u_int16_t length_of_sa_payload = SA_PAYLOAD_HEADER_LENGTH;
769 u_int16_t int16_val;
770 /* proposals are stored in a linked list and so accessed */
771 linked_list_t *proposals = *((linked_list_t **)(this->data_struct + rules[i].offset));
772
773 this->logger->log(this->logger,CONTROL_MORE,"Generate Proposals");
774
775 linked_list_iterator_t *iterator;
776 /* create forward iterator */
777 status = proposals->create_iterator(proposals,&iterator,TRUE);
778 if (status != SUCCESS)
779 {
780 this->logger->log(this->logger,CONTROL_MORE,"Could not iterator of proposals");
781 return status;
782 }
783 /* every proposal is processed (iterative call )*/
784 while (iterator->has_next(iterator))
785 {
786 payload_t *current_proposal;
787 u_int32_t before_generate_position_offset;
788 u_int32_t after_generate_position_offset;
789
790 status = iterator->current(iterator,(void **)&current_proposal);
791 if (status != SUCCESS)
792 {
793 iterator->destroy(iterator);
794 return status;
795 }
796 before_generate_position_offset = this->get_current_buffer_offset(this);
797 status = this->public.generate_payload(&(this->public),current_proposal);
798 after_generate_position_offset = this->get_current_buffer_offset(this);
799 if (status != SUCCESS)
800 {
801 iterator->destroy(iterator);
802 return status;
803 }
804
805 /* increase size of transform */
806 length_of_sa_payload += (after_generate_position_offset - before_generate_position_offset);
807 }
808 iterator->destroy(iterator);
809 this->logger->log(this->logger,CONTROL_MORE,"Length of Payload is %d, offset is %d",length_of_sa_payload,payload_length_position_offset);
810
811 int16_val = htons(length_of_sa_payload);
812 status = this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),payload_length_position_offset);
813 if (status != SUCCESS)
814 {
815 this->logger->log(this->logger,CONTROL_MORE,"Could no write payload length into buffer");
816 return status;
817 }
818 break;
819 }
820
821 case TRANSFORMS:
822 {
823 /* before iterative generate the transforms, store the current length position */
824 u_int32_t payload_length_position_offset = this->last_payload_length_position_offset;
825 u_int16_t length_of_proposal = PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH + this->last_spi_size;
826 u_int16_t int16_val;
827 linked_list_t *transforms = *((linked_list_t **)(this->data_struct + rules[i].offset));
828 linked_list_iterator_t *iterator;
829
830 this->logger->log(this->logger,CONTROL_MORE,"Generate Transforms");
831
832 /* create forward iterator */
833 status = transforms->create_iterator(transforms,&iterator,TRUE);
834 if (status != SUCCESS)
835 {
836 return status;
837 }
838 while (iterator->has_next(iterator))
839 {
840 payload_t *current_transform;
841 u_int32_t before_generate_position_offset;
842 u_int32_t after_generate_position_offset;
843
844 status = iterator->current(iterator,(void **)&current_transform);
845 if (status != SUCCESS)
846 {
847 iterator->destroy(iterator);
848 return status;
849 }
850
851 before_generate_position_offset = this->get_current_buffer_offset(this);
852 status = this->public.generate_payload(&(this->public),current_transform);
853 after_generate_position_offset = this->get_current_buffer_offset(this);
854 if (status != SUCCESS)
855 {
856 iterator->destroy(iterator);
857 return status;
858 }
859
860 /* increase size of transform */
861 length_of_proposal += (after_generate_position_offset - before_generate_position_offset);
862 }
863
864 iterator->destroy(iterator);
865
866 this->logger->log(this->logger,CONTROL_MORE,"Length of Transform is %d, offset is %d",length_of_proposal,payload_length_position_offset);
867
868 int16_val = htons(length_of_proposal);
869 this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),payload_length_position_offset);
870
871 break;
872 }
873 case TRANSFORM_ATTRIBUTES:
874 {
875 this->logger->log(this->logger,CONTROL_MORE,"Generate Transform attributes");
876 /* before iterative generate the transform attributes, store the current length position */
877 u_int32_t transform_length_position_offset = this->last_payload_length_position_offset;
878
879 u_int16_t length_of_transform = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
880 u_int16_t int16_val;
881 linked_list_t *transform_attributes =*((linked_list_t **)(this->data_struct + rules[i].offset));
882
883 linked_list_iterator_t *iterator;
884 /* create forward iterator */
885 status = transform_attributes->create_iterator(transform_attributes,&iterator,TRUE);
886 if (status != SUCCESS)
887 {
888 return status;
889 }
890 while (iterator->has_next(iterator))
891 {
892 payload_t *current_attribute;
893 u_int32_t before_generate_position_offset;
894 u_int32_t after_generate_position_offset;
895
896 status = iterator->current(iterator,(void **)&current_attribute);
897 if (status != SUCCESS)
898 {
899 iterator->destroy(iterator);
900 return status;
901 }
902
903 before_generate_position_offset = this->get_current_buffer_offset(this);
904 this->public.generate_payload(&(this->public),current_attribute);
905 after_generate_position_offset = this->get_current_buffer_offset(this);
906
907 /* increase size of transform */
908 length_of_transform += (after_generate_position_offset - before_generate_position_offset);
909 }
910
911 iterator->destroy(iterator);
912
913 this->logger->log(this->logger,CONTROL_MORE,"Length of Transform is %d, offset is %d",length_of_transform,transform_length_position_offset);
914
915 int16_val = htons(length_of_transform);
916 this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),transform_length_position_offset);
917
918 break;
919 }
920 case ATTRIBUTE_FORMAT:
921 {
922 status = this->generate_flag(this,rules[i].offset);
923 /* Attribute format is a flag which is stored in context*/
924 this->attribute_format = *((bool *) (this->data_struct + rules[i].offset));
925 break;
926 }
927
928 case ATTRIBUTE_LENGTH_OR_VALUE:
929 {
930 this->logger->log(this->logger,CONTROL_MORE,"Generate Attribute Length or Value field");
931 if (this->attribute_format == FALSE)
932 {
933 status = this->generate_u_int_type(this,U_INT_16,rules[i].offset);
934 /* this field hold the length of the attribute */
935 this->attribute_length = *((u_int16_t *)(this->data_struct + rules[i].offset));
936 }
937 else
938 {
939 status = this->write_bytes_to_buffer(this,(this->data_struct + rules[i].offset),2);
940 }
941 break;
942 }
943 case ATTRIBUTE_VALUE:
944 {
945 if (this->attribute_format == FALSE)
946 {
947 this->logger->log(this->logger,CONTROL_MORE,"Attribute value has not fixed size");
948 /* the attribute value is generated */
949 status = this->generate_from_chunk(this,rules[i].offset);
950 }
951 break;
952 }
953 default:
954 this->logger->log(this->logger,CONTROL_MORE,"Field Type %s is not supported",mapping_find(encoding_type_t_mappings,rules[i].type));
955 return NOT_SUPPORTED;
956 }
957 }
958
959 return status;
960 }
961
962 /**
963 * Implements generator_t's destroy function.
964 * See #generator_s.destroy.
965 */
966 static status_t destroy(private_generator_t *this)
967 {
968 allocator_free(this->buffer);
969 global_logger_manager->destroy_logger(global_logger_manager,this->logger);
970 allocator_free(this);
971 return SUCCESS;
972 }
973
974 /*
975 * Described in header
976 */
977 generator_t * generator_create()
978 {
979 private_generator_t *this;
980
981 this = allocator_alloc_thing(private_generator_t);
982 if (this == NULL)
983 {
984 return NULL;
985 }
986
987 /* initiate public functions */
988 this->public.generate_payload = (status_t(*)(generator_t*, payload_t *)) generate_payload;
989 this->public.destroy = (status_t(*)(generator_t*)) destroy;
990 this->public.write_to_chunk = (status_t (*) (generator_t *,chunk_t *)) write_to_chunk;
991
992
993 /* initiate private functions */
994 this->get_current_buffer_size = get_current_buffer_size;
995 this->get_current_buffer_space = get_current_buffer_space;
996 this->get_current_data_length = get_current_data_length;
997 this->get_current_buffer_offset = get_current_buffer_offset;
998 this->generate_u_int_type = generate_u_int_type;
999 this->generate_reserved_field = generate_reserved_field;
1000 this->generate_flag = generate_flag;
1001 this->generate_from_chunk = generate_from_chunk;
1002 this->make_space_available = make_space_available;
1003 this->write_bytes_to_buffer = write_bytes_to_buffer;
1004 this->write_bytes_to_buffer_at_offset = write_bytes_to_buffer_at_offset;
1005
1006
1007 /* allocate memory for buffer */
1008 this->buffer = allocator_alloc(GENERATOR_DATA_BUFFER_SIZE);
1009 if (this->buffer == NULL)
1010 {
1011 allocator_free(this);
1012 return NULL;
1013 }
1014
1015 /* initiate private variables */
1016 this->out_position = this->buffer;
1017 this->roof_position = this->buffer + GENERATOR_DATA_BUFFER_SIZE;
1018 this->data_struct = NULL;
1019 this->current_bit = 0;
1020 this->last_payload_length_position_offset = 0;
1021 this->header_length_position_offset = 0;
1022 this->logger = global_logger_manager->create_logger(global_logger_manager,GENERATOR,NULL);
1023
1024 if (this->logger == NULL)
1025 {
1026 allocator_free(this->buffer);
1027 allocator_free(this);
1028 return NULL;
1029 }
1030 return &(this->public);
1031 }