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