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