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