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