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