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