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