Moving charon to libcharon.
[strongswan.git] / src / libcharon / encoding / generator.c
1 /*
2 * Copyright (C) 2005-2009 Martin Willi
3 * Copyright (C) 2005 Jan Hutter
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include <stdlib.h>
18 #include <string.h>
19 #include <arpa/inet.h>
20 #include <stdio.h>
21
22 #include "generator.h"
23
24 #include <library.h>
25 #include <daemon.h>
26 #include <utils/linked_list.h>
27 #include <encoding/payloads/payload.h>
28 #include <encoding/payloads/proposal_substructure.h>
29 #include <encoding/payloads/transform_substructure.h>
30 #include <encoding/payloads/sa_payload.h>
31 #include <encoding/payloads/ke_payload.h>
32 #include <encoding/payloads/notify_payload.h>
33 #include <encoding/payloads/nonce_payload.h>
34 #include <encoding/payloads/id_payload.h>
35 #include <encoding/payloads/auth_payload.h>
36 #include <encoding/payloads/cert_payload.h>
37 #include <encoding/payloads/certreq_payload.h>
38 #include <encoding/payloads/ts_payload.h>
39 #include <encoding/payloads/delete_payload.h>
40 #include <encoding/payloads/vendor_id_payload.h>
41 #include <encoding/payloads/cp_payload.h>
42 #include <encoding/payloads/configuration_attribute.h>
43 #include <encoding/payloads/eap_payload.h>
44
45
46 typedef struct private_generator_t private_generator_t;
47
48 /**
49 * Private part of a generator_t object.
50 */
51 struct private_generator_t {
52 /**
53 * Public part of a generator_t object.
54 */
55 generator_t public;
56
57 /**
58 * Buffer used to generate the data into.
59 */
60 u_int8_t *buffer;
61
62 /**
63 * Current write position in buffer (one byte aligned).
64 */
65 u_int8_t *out_position;
66
67 /**
68 * Position of last byte in buffer.
69 */
70 u_int8_t *roof_position;
71
72 /**
73 * Current bit writing to in current byte (between 0 and 7).
74 */
75 u_int8_t current_bit;
76
77 /**
78 * Associated data struct to read informations from.
79 */
80 void *data_struct;
81
82 /*
83 * Last payload length position offset in the buffer.
84 */
85 u_int32_t last_payload_length_position_offset;
86
87 /**
88 * Offset of the header length field in the buffer.
89 */
90 u_int32_t header_length_position_offset;
91
92 /**
93 * Last SPI size.
94 */
95 u_int8_t last_spi_size;
96
97 /**
98 * Attribute format of the last generated transform attribute.
99 *
100 * Used to check if a variable value field is used or not for
101 * the transform attribute value.
102 */
103 bool attribute_format;
104
105 /**
106 * Depending on the value of attribute_format this field is used
107 * to hold the length of the transform attribute in bytes.
108 */
109 u_int16_t attribute_length;
110 };
111
112 /**
113 * Get size of current buffer in bytes.
114 */
115 static int get_size(private_generator_t *this)
116 {
117 return this->roof_position - this->buffer;
118 }
119
120 /**
121 * Get free space of current buffer in bytes.
122 */
123 static int get_space(private_generator_t *this)
124 {
125 return this->roof_position - this->out_position;
126 }
127
128 /**
129 * Get length of data in buffer (in bytes).
130 */
131 static int get_length(private_generator_t *this)
132 {
133 return this->out_position - this->buffer;
134 }
135
136 /**
137 * Get current offset in buffer (in bytes).
138 */
139 static u_int32_t get_offset(private_generator_t *this)
140 {
141 return this->out_position - this->buffer;
142 }
143
144 /**
145 * Makes sure enough space is available in buffer to store amount of bits.
146 */
147 static void make_space_available(private_generator_t *this, int bits)
148 {
149 while ((get_space(this) * 8 - this->current_bit) < bits)
150 {
151 int old_buffer_size, new_buffer_size, out_position_offset;
152
153 old_buffer_size = get_size(this);
154 new_buffer_size = old_buffer_size + GENERATOR_DATA_BUFFER_INCREASE_VALUE;
155 out_position_offset = this->out_position - this->buffer;
156
157 DBG2(DBG_ENC, "increasing gen buffer from %d to %d byte",
158 old_buffer_size, new_buffer_size);
159
160 this->buffer = realloc(this->buffer,new_buffer_size);
161 this->out_position = (this->buffer + out_position_offset);
162 this->roof_position = (this->buffer + new_buffer_size);
163 }
164 }
165
166 /**
167 * Writes a specific amount of byte into the buffer.
168 */
169 static void write_bytes_to_buffer(private_generator_t *this, void *bytes,
170 int number_of_bytes)
171 {
172 int i;
173 u_int8_t *read_position = (u_int8_t *)bytes;
174
175 make_space_available(this, number_of_bytes * 8);
176
177 for (i = 0; i < number_of_bytes; i++)
178 {
179 *(this->out_position) = *(read_position);
180 read_position++;
181 this->out_position++;
182 }
183 }
184
185 /**
186 * Writes a specific amount of byte into the buffer at a specific offset.
187 */
188 static void write_bytes_to_buffer_at_offset(private_generator_t *this,
189 void *bytes, int number_of_bytes, u_int32_t offset)
190 {
191 int i;
192 u_int8_t *read_position = (u_int8_t *)bytes;
193 u_int8_t *write_position;
194 u_int32_t free_space_after_offset = get_size(this) - offset;
195
196 /* check first if enough space for new data is available */
197 if (number_of_bytes > free_space_after_offset)
198 {
199 make_space_available(this,
200 (number_of_bytes - free_space_after_offset) * 8);
201 }
202
203 write_position = this->buffer + offset;
204 for (i = 0; i < number_of_bytes; i++)
205 {
206 *write_position = *read_position;
207 read_position++;
208 write_position++;
209 }
210 }
211
212 /**
213 * Generates a U_INT-Field type and writes it to buffer.
214 */
215 static void generate_u_int_type(private_generator_t *this,
216 encoding_type_t int_type,u_int32_t offset)
217 {
218 int number_of_bits = 0;
219
220 /* find out number of bits of each U_INT type to check for enough space */
221 switch (int_type)
222 {
223 case U_INT_4:
224 number_of_bits = 4;
225 break;
226 case TS_TYPE:
227 case U_INT_8:
228 number_of_bits = 8;
229 break;
230 case U_INT_16:
231 case CONFIGURATION_ATTRIBUTE_LENGTH:
232 number_of_bits = 16;
233 break;
234 case U_INT_32:
235 number_of_bits = 32;
236 break;
237 case ATTRIBUTE_TYPE:
238 number_of_bits = 15;
239 break;
240 case IKE_SPI:
241 number_of_bits = 64;
242 break;
243 default:
244 DBG1(DBG_ENC, "U_INT Type %N is not supported",
245 encoding_type_names, int_type);
246 return;
247 }
248 if ((number_of_bits % 8) == 0 && this->current_bit != 0)
249 {
250 DBG1(DBG_ENC, "U_INT Type %N is not 8 Bit aligned",
251 encoding_type_names, int_type);
252 return;
253 }
254
255 make_space_available(this, number_of_bits);
256 switch (int_type)
257 {
258 case U_INT_4:
259 {
260 u_int8_t high, low;
261
262 if (this->current_bit == 0)
263 {
264 /* high of current byte in buffer has to be set to the new value*/
265 high = *((u_int8_t *)(this->data_struct + offset)) << 4;
266 /* low in buffer is not changed */
267 low = *(this->out_position) & 0x0F;
268 /* high is set, low_val is not changed */
269 *(this->out_position) = high | low;
270 DBG3(DBG_ENC, " => %d", *(this->out_position));
271 /* write position is not changed, just bit position is moved */
272 this->current_bit = 4;
273 }
274 else if (this->current_bit == 4)
275 {
276 /* high in buffer is not changed */
277 high = *(this->out_position) & 0xF0;
278 /* low of current byte in buffer has to be set to the new value*/
279 low = *((u_int8_t *)(this->data_struct + offset)) & 0x0F;
280 *(this->out_position) = high | low;
281 DBG3(DBG_ENC, " => %d", *(this->out_position));
282 this->out_position++;
283 this->current_bit = 0;
284 }
285 else
286 {
287 DBG1(DBG_ENC, "U_INT_4 Type is not 4 Bit aligned");
288 /* 4 Bit integers must have a 4 bit alignment */
289 return;
290 }
291 break;
292 }
293 case TS_TYPE:
294 case U_INT_8:
295 {
296 /* 8 bit values are written as they are */
297 *this->out_position = *((u_int8_t *)(this->data_struct + offset));
298 DBG3(DBG_ENC, " => %d", *(this->out_position));
299 this->out_position++;
300 break;
301 }
302 case ATTRIBUTE_TYPE:
303 {
304 u_int8_t attribute_format_flag;
305 u_int16_t val;
306
307 /* attribute type must not change first bit of current byte */
308 if (this->current_bit != 1)
309 {
310 DBG1(DBG_ENC, "ATTRIBUTE FORMAT flag is not set");
311 return;
312 }
313 attribute_format_flag = *(this->out_position) & 0x80;
314 /* get attribute type value as 16 bit integer*/
315 val = *((u_int16_t*)(this->data_struct + offset));
316 /* unset most significant bit */
317 val &= 0x7FFF;
318 if (attribute_format_flag)
319 {
320 val |= 0x8000;
321 }
322 val = htons(val);
323 DBG3(DBG_ENC, " => %d", val);
324 /* write bytes to buffer (set bit is overwritten) */
325 write_bytes_to_buffer(this, &val, sizeof(u_int16_t));
326 this->current_bit = 0;
327 break;
328
329 }
330 case U_INT_16:
331 case CONFIGURATION_ATTRIBUTE_LENGTH:
332 {
333 u_int16_t val = htons(*((u_int16_t*)(this->data_struct + offset)));
334 DBG3(DBG_ENC, " => %b", &val, sizeof(u_int16_t));
335 write_bytes_to_buffer(this, &val, sizeof(u_int16_t));
336 break;
337 }
338 case U_INT_32:
339 {
340 u_int32_t val = htonl(*((u_int32_t*)(this->data_struct + offset)));
341 DBG3(DBG_ENC, " => %b", &val, sizeof(u_int32_t));
342 write_bytes_to_buffer(this, &val, sizeof(u_int32_t));
343 break;
344 }
345 case IKE_SPI:
346 {
347 /* 64 bit are written as-is, no host order conversion */
348 write_bytes_to_buffer(this, this->data_struct + offset,
349 sizeof(u_int64_t));
350 DBG3(DBG_ENC, " => %b", this->data_struct + offset,
351 sizeof(u_int64_t));
352 break;
353 }
354 default:
355 {
356 DBG1(DBG_ENC, "U_INT Type %N is not supported",
357 encoding_type_names, int_type);
358 return;
359 }
360 }
361 }
362
363 /**
364 * Generate a reserved bit or byte
365 */
366 static void generate_reserved_field(private_generator_t *this, int bits)
367 {
368 /* only one bit or 8 bit fields are supported */
369 if (bits != 1 && bits != 8)
370 {
371 DBG1(DBG_ENC, "reserved field of %d bits cannot be generated", bits);
372 return ;
373 }
374 make_space_available(this, bits);
375
376 if (bits == 1)
377 {
378 u_int8_t reserved_bit = ~(1 << (7 - this->current_bit));
379
380 *(this->out_position) = *(this->out_position) & reserved_bit;
381 if (this->current_bit == 0)
382 {
383 /* memory must be zero */
384 *(this->out_position) = 0x00;
385 }
386 this->current_bit++;
387 if (this->current_bit >= 8)
388 {
389 this->current_bit = this->current_bit % 8;
390 this->out_position++;
391 }
392 }
393 else
394 {
395 if (this->current_bit > 0)
396 {
397 DBG1(DBG_ENC, "reserved field cannot be written cause "
398 "alignement of current bit is %d", this->current_bit);
399 return;
400 }
401 *(this->out_position) = 0x00;
402 this->out_position++;
403 }
404 }
405
406 /**
407 * Generate a FLAG filed
408 */
409 static void generate_flag(private_generator_t *this, u_int32_t offset)
410 {
411 u_int8_t flag_value;
412 u_int8_t flag;
413
414 flag_value = (*((bool *) (this->data_struct + offset))) ? 1 : 0;
415 /* get flag position */
416 flag = (flag_value << (7 - this->current_bit));
417
418 /* make sure one bit is available in buffer */
419 make_space_available(this, 1);
420 if (this->current_bit == 0)
421 {
422 /* memory must be zero */
423 *(this->out_position) = 0x00;
424 }
425
426 *(this->out_position) = *(this->out_position) | flag;
427 DBG3(DBG_ENC, " => %d", *this->out_position);
428
429 this->current_bit++;
430 if (this->current_bit >= 8)
431 {
432 this->current_bit = this->current_bit % 8;
433 this->out_position++;
434 }
435 }
436
437 /**
438 * Generates a bytestream from a chunk_t.
439 */
440 static void generate_from_chunk(private_generator_t *this, u_int32_t offset)
441 {
442 chunk_t *value;
443
444 if (this->current_bit != 0)
445 {
446 DBG1(DBG_ENC, "can not generate a chunk at Bitpos %d", this->current_bit);
447 return ;
448 }
449
450 value = (chunk_t *)(this->data_struct + offset);
451 DBG3(DBG_ENC, " => %B", value);
452
453 write_bytes_to_buffer(this, value->ptr, value->len);
454 }
455
456 /**
457 * Implementation of private_generator_t.write_to_chunk.
458 */
459 static void write_to_chunk(private_generator_t *this,chunk_t *data)
460 {
461 int data_length = get_length(this);
462 u_int32_t header_length_field = data_length;
463
464 /* write length into header length field */
465 if (this->header_length_position_offset > 0)
466 {
467 u_int32_t val = htonl(header_length_field);
468 write_bytes_to_buffer_at_offset(this, &val, sizeof(u_int32_t),
469 this->header_length_position_offset);
470 }
471
472 if (this->current_bit > 0)
473 {
474 data_length++;
475 }
476 *data = chunk_alloc(data_length);
477 memcpy(data->ptr, this->buffer, data_length);
478
479 DBG3(DBG_ENC, "generated data of this generator %B", data);
480 }
481
482 /**
483 * Implementation of private_generator_t.generate_payload.
484 */
485 static void generate_payload (private_generator_t *this,payload_t *payload)
486 {
487 int i, offset_start;
488 size_t rule_count;
489 encoding_rule_t *rules;
490 payload_type_t payload_type;
491
492 this->data_struct = payload;
493 payload_type = payload->get_type(payload);
494 /* spi size has to get reseted */
495 this->last_spi_size = 0;
496
497 offset_start = this->out_position - this->buffer;
498
499 DBG2(DBG_ENC, "generating payload of type %N",
500 payload_type_names, payload_type);
501
502 /* each payload has its own encoding rules */
503 payload->get_encoding_rules(payload, &rules, &rule_count);
504
505 for (i = 0; i < rule_count;i++)
506 {
507 DBG2(DBG_ENC, " generating rule %d %N",
508 i, encoding_type_names, rules[i].type);
509 switch (rules[i].type)
510 {
511 case U_INT_4:
512 case U_INT_8:
513 case U_INT_16:
514 case U_INT_32:
515 case IKE_SPI:
516 case TS_TYPE:
517 case ATTRIBUTE_TYPE:
518 case CONFIGURATION_ATTRIBUTE_LENGTH:
519 {
520 generate_u_int_type(this, rules[i].type, rules[i].offset);
521 break;
522 }
523 case RESERVED_BIT:
524 {
525 generate_reserved_field(this, 1);
526 break;
527 }
528 case RESERVED_BYTE:
529 {
530 generate_reserved_field(this, 8);
531 break;
532 }
533 case FLAG:
534 {
535 generate_flag(this, rules[i].offset);
536 break;
537 }
538 case PAYLOAD_LENGTH:
539 {
540 this->last_payload_length_position_offset = get_offset(this);
541 generate_u_int_type(this, U_INT_16,rules[i].offset);
542 break;
543 }
544 case HEADER_LENGTH:
545 {
546 this->header_length_position_offset = get_offset(this);
547 generate_u_int_type(this ,U_INT_32, rules[i].offset);
548 break;
549 }
550 case SPI_SIZE:
551 generate_u_int_type(this, U_INT_8, rules[i].offset);
552 this->last_spi_size = *((u_int8_t *)(this->data_struct +
553 rules[i].offset));
554 break;
555 case ADDRESS:
556 {
557 generate_from_chunk(this, rules[i].offset);
558 break;
559 }
560 case SPI:
561 {
562 generate_from_chunk(this, rules[i].offset);
563 break;
564 }
565 case KEY_EXCHANGE_DATA:
566 case NOTIFICATION_DATA:
567 case NONCE_DATA:
568 case ID_DATA:
569 case AUTH_DATA:
570 case CERT_DATA:
571 case CERTREQ_DATA:
572 case SPIS:
573 case CONFIGURATION_ATTRIBUTE_VALUE:
574 case VID_DATA:
575 case EAP_DATA:
576 {
577 u_int32_t payload_length_position_offset;
578 u_int16_t length_of_payload;
579 u_int16_t header_length = 0;
580 u_int16_t length_in_network_order;
581
582 switch(rules[i].type)
583 {
584 case KEY_EXCHANGE_DATA:
585 header_length = KE_PAYLOAD_HEADER_LENGTH;
586 break;
587 case NOTIFICATION_DATA:
588 header_length = NOTIFY_PAYLOAD_HEADER_LENGTH +
589 this->last_spi_size;
590 break;
591 case NONCE_DATA:
592 header_length = NONCE_PAYLOAD_HEADER_LENGTH;
593 break;
594 case ID_DATA:
595 header_length = ID_PAYLOAD_HEADER_LENGTH;
596 break;
597 case AUTH_DATA:
598 header_length = AUTH_PAYLOAD_HEADER_LENGTH;
599 break;
600 case CERT_DATA:
601 header_length = CERT_PAYLOAD_HEADER_LENGTH;
602 break;
603 case CERTREQ_DATA:
604 header_length = CERTREQ_PAYLOAD_HEADER_LENGTH;
605 break;
606 case SPIS:
607 header_length = DELETE_PAYLOAD_HEADER_LENGTH;
608 break;
609 case VID_DATA:
610 header_length = VENDOR_ID_PAYLOAD_HEADER_LENGTH;
611 break;
612 case CONFIGURATION_ATTRIBUTE_VALUE:
613 header_length = CONFIGURATION_ATTRIBUTE_HEADER_LENGTH;
614 break;
615 case EAP_DATA:
616 header_length = EAP_PAYLOAD_HEADER_LENGTH;
617 break;
618 default:
619 break;
620 }
621 generate_from_chunk(this, rules[i].offset);
622
623 payload_length_position_offset =
624 this->last_payload_length_position_offset;
625
626 length_of_payload = header_length +
627 ((chunk_t *)(this->data_struct + rules[i].offset))->len;
628
629 length_in_network_order = htons(length_of_payload);
630 write_bytes_to_buffer_at_offset(this, &length_in_network_order,
631 sizeof(u_int16_t), payload_length_position_offset);
632 break;
633 }
634 case PROPOSALS:
635 {
636 u_int32_t payload_length_position_offset =
637 this->last_payload_length_position_offset;
638 /* Length of SA_PAYLOAD is calculated */
639 u_int16_t length_of_sa_payload = SA_PAYLOAD_HEADER_LENGTH;
640 u_int16_t int16_val;
641 linked_list_t *proposals = *((linked_list_t **)
642 (this->data_struct + rules[i].offset));
643 iterator_t *iterator;
644 payload_t *current_proposal;
645
646 iterator = proposals->create_iterator(proposals,TRUE);
647 while (iterator->iterate(iterator, (void**)&current_proposal))
648 {
649 u_int32_t before_generate_position_offset;
650 u_int32_t after_generate_position_offset;
651
652 before_generate_position_offset = get_offset(this);
653 generate_payload(this, current_proposal);
654 after_generate_position_offset = get_offset(this);
655 length_of_sa_payload += (after_generate_position_offset -
656 before_generate_position_offset);
657 }
658 iterator->destroy(iterator);
659
660 int16_val = htons(length_of_sa_payload);
661 write_bytes_to_buffer_at_offset(this, &int16_val,
662 sizeof(u_int16_t),payload_length_position_offset);
663 break;
664 }
665 case TRANSFORMS:
666 {
667 u_int32_t payload_length_position_offset =
668 this->last_payload_length_position_offset;
669 u_int16_t length_of_proposal =
670 PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH + this->last_spi_size;
671 u_int16_t int16_val;
672 linked_list_t *transforms = *((linked_list_t **)
673 (this->data_struct + rules[i].offset));
674 iterator_t *iterator;
675 payload_t *current_transform;
676
677 iterator = transforms->create_iterator(transforms,TRUE);
678 while (iterator->iterate(iterator, (void**)&current_transform))
679 {
680 u_int32_t before_generate_position_offset;
681 u_int32_t after_generate_position_offset;
682
683 before_generate_position_offset = get_offset(this);
684 generate_payload(this, current_transform);
685 after_generate_position_offset = get_offset(this);
686
687 length_of_proposal += (after_generate_position_offset -
688 before_generate_position_offset);
689 }
690 iterator->destroy(iterator);
691
692 int16_val = htons(length_of_proposal);
693 write_bytes_to_buffer_at_offset(this, &int16_val,
694 sizeof(u_int16_t), payload_length_position_offset);
695 break;
696 }
697 case TRANSFORM_ATTRIBUTES:
698 {
699 u_int32_t transform_length_position_offset =
700 this->last_payload_length_position_offset;
701 u_int16_t length_of_transform =
702 TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
703 u_int16_t int16_val;
704 linked_list_t *transform_attributes =*((linked_list_t **)
705 (this->data_struct + rules[i].offset));
706 iterator_t *iterator;
707 payload_t *current_attribute;
708
709 iterator = transform_attributes->create_iterator(
710 transform_attributes, TRUE);
711 while (iterator->iterate(iterator, (void**)&current_attribute))
712 {
713 u_int32_t before_generate_position_offset;
714 u_int32_t after_generate_position_offset;
715
716 before_generate_position_offset = get_offset(this);
717 generate_payload(this, current_attribute);
718 after_generate_position_offset = get_offset(this);
719
720 length_of_transform += (after_generate_position_offset -
721 before_generate_position_offset);
722 }
723
724 iterator->destroy(iterator);
725
726 int16_val = htons(length_of_transform);
727 write_bytes_to_buffer_at_offset(this, &int16_val,
728 sizeof(u_int16_t),transform_length_position_offset);
729 break;
730 }
731 case CONFIGURATION_ATTRIBUTES:
732 {
733 u_int32_t configurations_length_position_offset =
734 this->last_payload_length_position_offset;
735 u_int16_t length_of_configurations = CP_PAYLOAD_HEADER_LENGTH;
736 u_int16_t int16_val;
737 linked_list_t *configuration_attributes = *((linked_list_t **)
738 (this->data_struct + rules[i].offset));
739 iterator_t *iterator;
740 payload_t *current_attribute;
741
742 iterator = configuration_attributes->create_iterator(
743 configuration_attributes,TRUE);
744 while (iterator->iterate(iterator, (void**)&current_attribute))
745 {
746 u_int32_t before_generate_position_offset;
747 u_int32_t after_generate_position_offset;
748
749 before_generate_position_offset = get_offset(this);
750 generate_payload(this, current_attribute);
751 after_generate_position_offset = get_offset(this);
752
753 length_of_configurations += after_generate_position_offset -
754 before_generate_position_offset;
755 }
756
757 iterator->destroy(iterator);
758
759 int16_val = htons(length_of_configurations);
760 write_bytes_to_buffer_at_offset(this, &int16_val,
761 sizeof(u_int16_t),configurations_length_position_offset);
762 break;
763 }
764 case ATTRIBUTE_FORMAT:
765 {
766 generate_flag(this, rules[i].offset);
767 /* Attribute format is a flag which is stored in context*/
768 this->attribute_format =
769 *((bool *)(this->data_struct + rules[i].offset));
770 break;
771 }
772
773 case ATTRIBUTE_LENGTH_OR_VALUE:
774 {
775 if (this->attribute_format == FALSE)
776 {
777 generate_u_int_type(this, U_INT_16, rules[i].offset);
778 /* this field hold the length of the attribute */
779 this->attribute_length =
780 *((u_int16_t *)(this->data_struct + rules[i].offset));
781 }
782 else
783 {
784 generate_u_int_type(this, U_INT_16, rules[i].offset);
785 }
786 break;
787 }
788 case ATTRIBUTE_VALUE:
789 {
790 if (this->attribute_format == FALSE)
791 {
792 DBG2(DBG_ENC, "attribute value has not fixed size");
793 /* the attribute value is generated */
794 generate_from_chunk(this, rules[i].offset);
795 }
796 break;
797 }
798 case TRAFFIC_SELECTORS:
799 {
800 u_int32_t payload_length_position_offset =
801 this->last_payload_length_position_offset;
802 u_int16_t length_of_ts_payload = TS_PAYLOAD_HEADER_LENGTH;
803 u_int16_t int16_val;
804 linked_list_t *traffic_selectors = *((linked_list_t **)
805 (this->data_struct + rules[i].offset));
806 iterator_t *iterator;
807 payload_t *current_tss;
808
809 iterator = traffic_selectors->create_iterator(
810 traffic_selectors,TRUE);
811 while (iterator->iterate(iterator, (void **)&current_tss))
812 {
813 u_int32_t before_generate_position_offset;
814 u_int32_t after_generate_position_offset;
815
816 before_generate_position_offset = get_offset(this);
817 generate_payload(this, current_tss);
818 after_generate_position_offset = get_offset(this);
819
820 length_of_ts_payload += (after_generate_position_offset -
821 before_generate_position_offset);
822 }
823 iterator->destroy(iterator);
824
825 int16_val = htons(length_of_ts_payload);
826 write_bytes_to_buffer_at_offset(this, &int16_val,
827 sizeof(u_int16_t),payload_length_position_offset);
828 break;
829 }
830
831 case ENCRYPTED_DATA:
832 {
833 generate_from_chunk(this, rules[i].offset);
834 break;
835 }
836 default:
837 DBG1(DBG_ENC, "field type %N is not supported",
838 encoding_type_names, rules[i].type);
839 return;
840 }
841 }
842 DBG2(DBG_ENC, "generating %N payload finished",
843 payload_type_names, payload_type);
844 DBG3(DBG_ENC, "generated data for this payload %b",
845 this->buffer + offset_start,
846 this->out_position - this->buffer - offset_start);
847 }
848
849 /**
850 * Implementation of generator_t.destroy.
851 */
852 static status_t destroy(private_generator_t *this)
853 {
854 free(this->buffer);
855 free(this);
856 return SUCCESS;
857 }
858
859 /*
860 * Described in header
861 */
862 generator_t *generator_create()
863 {
864 private_generator_t *this;
865
866 this = malloc_thing(private_generator_t);
867
868 /* initiate public functions */
869 this->public.generate_payload = (void(*)(generator_t*, payload_t *))generate_payload;
870 this->public.destroy = (void(*)(generator_t*)) destroy;
871 this->public.write_to_chunk = (void (*) (generator_t *,chunk_t *))write_to_chunk;
872
873 /* allocate memory for buffer */
874 this->buffer = malloc(GENERATOR_DATA_BUFFER_SIZE);
875
876 /* initiate private variables */
877 this->out_position = this->buffer;
878 this->roof_position = this->buffer + GENERATOR_DATA_BUFFER_SIZE;
879 this->data_struct = NULL;
880 this->current_bit = 0;
881 this->last_payload_length_position_offset = 0;
882 this->header_length_position_offset = 0;
883 this->attribute_format = FALSE;
884 this->attribute_length = 0;
885
886 return &(this->public);
887 }
888