- implemented and tested cert_payload_t
[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 {
738 /* the Key Exchange Data value is generated from chunk */
739 this->generate_from_chunk(this,rules[i].offset);
740
741 u_int32_t payload_length_position_offset = this->last_payload_length_position_offset;
742 /* Length of KE_PAYLOAD is calculated */
743 u_int16_t length_of_ke_payload = KE_PAYLOAD_HEADER_LENGTH + ((chunk_t *)(this->data_struct + rules[i].offset))->len;
744
745 u_int16_t int16_val = htons(length_of_ke_payload);
746 this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),payload_length_position_offset);
747 break;
748 }
749 case NOTIFICATION_DATA:
750 {
751 /* the Notification Data value is generated from chunk */
752 this->generate_from_chunk(this,rules[i].offset);
753
754 u_int32_t payload_length_position_offset = this->last_payload_length_position_offset;
755 /* Length of Notification PAYLOAD is calculated */
756 u_int16_t length_of_notify_payload = NOTIFY_PAYLOAD_HEADER_LENGTH + ((chunk_t *)(this->data_struct + rules[i].offset))->len;
757 length_of_notify_payload += this->last_spi_size;
758 u_int16_t int16_val = htons(length_of_notify_payload);
759
760 this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),payload_length_position_offset);
761 break;
762 }
763 case NONCE_DATA:
764 {
765 /* the Nonce Data value is generated from chunk */
766 this->generate_from_chunk(this, rules[i].offset);
767
768 u_int32_t payload_length_position_offset = this->last_payload_length_position_offset;
769 /* Length of nonce PAYLOAD is calculated */
770 u_int16_t length_of_nonce_payload = NONCE_PAYLOAD_HEADER_LENGTH + ((chunk_t *)(this->data_struct + rules[i].offset))->len;
771 u_int16_t int16_val = htons(length_of_nonce_payload);
772
773 this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),payload_length_position_offset);
774 break;
775 }
776 case ID_DATA:
777 {
778 /* the ID Data value is generated from chunk */
779 this->generate_from_chunk(this, rules[i].offset);
780
781 u_int32_t payload_length_position_offset = this->last_payload_length_position_offset;
782 /* Length of nonce PAYLOAD is calculated */
783 u_int16_t length_of_id_payload = ID_PAYLOAD_HEADER_LENGTH + ((chunk_t *)(this->data_struct + rules[i].offset))->len;
784 u_int16_t int16_val = htons(length_of_id_payload);
785
786 this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),payload_length_position_offset);
787 break;
788 }
789 case AUTH_DATA:
790 {
791 /* the AUTH Data value is generated from chunk */
792 this->generate_from_chunk(this, rules[i].offset);
793
794 u_int32_t payload_length_position_offset = this->last_payload_length_position_offset;
795 /* Length of nonce PAYLOAD is calculated */
796 u_int16_t length_of_auth_payload = AUTH_PAYLOAD_HEADER_LENGTH + ((chunk_t *)(this->data_struct + rules[i].offset))->len;
797 u_int16_t int16_val = htons(length_of_auth_payload);
798
799 this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),payload_length_position_offset);
800 break;
801 }
802 case CERT_DATA:
803 {
804 /* the CERT Data value is generated from chunk */
805 this->generate_from_chunk(this, rules[i].offset);
806
807 u_int32_t payload_length_position_offset = this->last_payload_length_position_offset;
808 /* Length of PAYLOAD is calculated */
809 u_int16_t length_of_cert_payload = CERT_PAYLOAD_HEADER_LENGTH + ((chunk_t *)(this->data_struct + rules[i].offset))->len;
810 u_int16_t int16_val = htons(length_of_cert_payload);
811
812 this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),payload_length_position_offset);
813 break;
814 }
815 case CERTREQ_DATA:
816 {
817 /* the CERTREQ Data value is generated from chunk */
818 this->generate_from_chunk(this, rules[i].offset);
819
820 u_int32_t payload_length_position_offset = this->last_payload_length_position_offset;
821 /* Length of PAYLOAD is calculated */
822 u_int16_t length_of_certreq_payload = CERTREQ_PAYLOAD_HEADER_LENGTH + ((chunk_t *)(this->data_struct + rules[i].offset))->len;
823 u_int16_t int16_val = htons(length_of_certreq_payload);
824
825 this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),payload_length_position_offset);
826 break;
827 }
828 case PROPOSALS:
829 {
830 /* before iterative generate the transforms, store the current payload length position */
831 u_int32_t payload_length_position_offset = this->last_payload_length_position_offset;
832 /* Length of SA_PAYLOAD is calculated */
833 u_int16_t length_of_sa_payload = SA_PAYLOAD_HEADER_LENGTH;
834 u_int16_t int16_val;
835 /* proposals are stored in a linked list and so accessed */
836 linked_list_t *proposals = *((linked_list_t **)(this->data_struct + rules[i].offset));
837
838 iterator_t *iterator;
839 /* create forward iterator */
840 iterator = proposals->create_iterator(proposals,TRUE);
841 /* every proposal is processed (iterative call )*/
842 while (iterator->has_next(iterator))
843 {
844 payload_t *current_proposal;
845 u_int32_t before_generate_position_offset;
846 u_int32_t after_generate_position_offset;
847
848 iterator->current(iterator,(void **)&current_proposal);
849
850 before_generate_position_offset = this->get_current_buffer_offset(this);
851 this->public.generate_payload(&(this->public),current_proposal);
852 after_generate_position_offset = this->get_current_buffer_offset(this);
853
854 /* increase size of transform */
855 length_of_sa_payload += (after_generate_position_offset - before_generate_position_offset);
856 }
857 iterator->destroy(iterator);
858
859 int16_val = htons(length_of_sa_payload);
860 this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),payload_length_position_offset);
861 break;
862 }
863 case TRANSFORMS:
864 {
865 /* before iterative generate the transforms, store the current length position */
866 u_int32_t payload_length_position_offset = this->last_payload_length_position_offset;
867 u_int16_t length_of_proposal = PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH + this->last_spi_size;
868 u_int16_t int16_val;
869 linked_list_t *transforms = *((linked_list_t **)(this->data_struct + rules[i].offset));
870 iterator_t *iterator;
871
872 /* create forward iterator */
873 iterator = transforms->create_iterator(transforms,TRUE);
874 while (iterator->has_next(iterator))
875 {
876 payload_t *current_transform;
877 u_int32_t before_generate_position_offset;
878 u_int32_t after_generate_position_offset;
879
880 iterator->current(iterator,(void **)&current_transform);
881
882 before_generate_position_offset = this->get_current_buffer_offset(this);
883 this->public.generate_payload(&(this->public),current_transform);
884 after_generate_position_offset = this->get_current_buffer_offset(this);
885
886 /* increase size of transform */
887 length_of_proposal += (after_generate_position_offset - before_generate_position_offset);
888 }
889
890 iterator->destroy(iterator);
891
892 int16_val = htons(length_of_proposal);
893 this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),payload_length_position_offset);
894
895 break;
896 }
897 case TRANSFORM_ATTRIBUTES:
898 {
899 /* before iterative generate the transform attributes, store the current length position */
900 u_int32_t transform_length_position_offset = this->last_payload_length_position_offset;
901
902 u_int16_t length_of_transform = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
903 u_int16_t int16_val;
904 linked_list_t *transform_attributes =*((linked_list_t **)(this->data_struct + rules[i].offset));
905
906 iterator_t *iterator;
907 /* create forward iterator */
908 iterator = transform_attributes->create_iterator(transform_attributes,TRUE);
909 while (iterator->has_next(iterator))
910 {
911 payload_t *current_attribute;
912 u_int32_t before_generate_position_offset;
913 u_int32_t after_generate_position_offset;
914
915 iterator->current(iterator,(void **)&current_attribute);
916
917 before_generate_position_offset = this->get_current_buffer_offset(this);
918 this->public.generate_payload(&(this->public),current_attribute);
919 after_generate_position_offset = this->get_current_buffer_offset(this);
920
921 /* increase size of transform */
922 length_of_transform += (after_generate_position_offset - before_generate_position_offset);
923 }
924
925 iterator->destroy(iterator);
926
927 int16_val = htons(length_of_transform);
928 this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),transform_length_position_offset);
929
930 break;
931 }
932 case ATTRIBUTE_FORMAT:
933 {
934 this->generate_flag(this,rules[i].offset);
935 /* Attribute format is a flag which is stored in context*/
936 this->attribute_format = *((bool *) (this->data_struct + rules[i].offset));
937 break;
938 }
939
940 case ATTRIBUTE_LENGTH_OR_VALUE:
941 {
942 if (this->attribute_format == FALSE)
943 {
944 this->generate_u_int_type(this,U_INT_16,rules[i].offset);
945 /* this field hold the length of the attribute */
946 this->attribute_length = *((u_int16_t *)(this->data_struct + rules[i].offset));
947 }
948 else
949 {
950 this->generate_u_int_type(this,U_INT_16,rules[i].offset);
951 // status = this->write_bytes_to_buffer(this,(this->data_struct + rules[i].offset),2);
952 }
953 break;
954 }
955 case ATTRIBUTE_VALUE:
956 {
957 if (this->attribute_format == FALSE)
958 {
959 this->logger->log(this->logger, CONTROL|ALL, "attribute value has not fixed size");
960 /* the attribute value is generated */
961 this->generate_from_chunk(this,rules[i].offset);
962 }
963 break;
964 }
965 case TRAFFIC_SELECTORS:
966 {
967 /* before iterative generate the traffic_selectors, store the current payload length position */
968 u_int32_t payload_length_position_offset = this->last_payload_length_position_offset;
969 /* Length of SA_PAYLOAD is calculated */
970 u_int16_t length_of_ts_payload = TS_PAYLOAD_HEADER_LENGTH;
971 u_int16_t int16_val;
972 /* traffic selectors are stored in a linked list and so accessed */
973 linked_list_t *traffic_selectors = *((linked_list_t **)(this->data_struct + rules[i].offset));
974
975 iterator_t *iterator;
976 /* create forward iterator */
977 iterator = traffic_selectors->create_iterator(traffic_selectors,TRUE);
978 /* every proposal is processed (iterative call )*/
979 while (iterator->has_next(iterator))
980 {
981 payload_t *current_traffic_selector_substructure;
982 u_int32_t before_generate_position_offset;
983 u_int32_t after_generate_position_offset;
984
985 iterator->current(iterator,(void **)&current_traffic_selector_substructure);
986
987 before_generate_position_offset = this->get_current_buffer_offset(this);
988 this->public.generate_payload(&(this->public),current_traffic_selector_substructure);
989 after_generate_position_offset = this->get_current_buffer_offset(this);
990
991 /* increase size of transform */
992 length_of_ts_payload += (after_generate_position_offset - before_generate_position_offset);
993 }
994 iterator->destroy(iterator);
995
996 int16_val = htons(length_of_ts_payload);
997 this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),payload_length_position_offset);
998 break;
999 }
1000
1001 case ENCRYPTED_DATA:
1002 {
1003 this->generate_from_chunk(this, rules[i].offset);
1004 break;
1005 }
1006 default:
1007 this->logger->log(this->logger, ERROR, "field type %s is not supported",
1008 mapping_find(encoding_type_m,rules[i].type));
1009 return;
1010 }
1011 }
1012 this->logger->log_bytes(this->logger, RAW|MORE, "generated data for this payload",
1013 payload_start, this->out_position-payload_start);
1014
1015 }
1016
1017 /**
1018 * Implementation of generator_t.destroy.
1019 */
1020 static status_t destroy(private_generator_t *this)
1021 {
1022 allocator_free(this->buffer);
1023 charon->logger_manager->destroy_logger(charon->logger_manager,this->logger);
1024 allocator_free(this);
1025 return SUCCESS;
1026 }
1027
1028 /*
1029 * Described in header
1030 */
1031 generator_t * generator_create()
1032 {
1033 private_generator_t *this;
1034
1035 this = allocator_alloc_thing(private_generator_t);
1036
1037 /* initiate public functions */
1038 this->public.generate_payload = (void(*)(generator_t*, payload_t *)) generate_payload;
1039 this->public.destroy = (void(*)(generator_t*)) destroy;
1040 this->public.write_to_chunk = (void (*) (generator_t *,chunk_t *)) write_to_chunk;
1041
1042
1043 /* initiate private functions */
1044 this->get_current_buffer_size = get_current_buffer_size;
1045 this->get_current_buffer_space = get_current_buffer_space;
1046 this->get_current_data_length = get_current_data_length;
1047 this->get_current_buffer_offset = get_current_buffer_offset;
1048 this->generate_u_int_type = generate_u_int_type;
1049 this->generate_reserved_field = generate_reserved_field;
1050 this->generate_flag = generate_flag;
1051 this->generate_from_chunk = generate_from_chunk;
1052 this->make_space_available = make_space_available;
1053 this->write_bytes_to_buffer = write_bytes_to_buffer;
1054 this->write_bytes_to_buffer_at_offset = write_bytes_to_buffer_at_offset;
1055
1056
1057 /* allocate memory for buffer */
1058 this->buffer = allocator_alloc(GENERATOR_DATA_BUFFER_SIZE);
1059
1060 /* initiate private variables */
1061 this->out_position = this->buffer;
1062 this->roof_position = this->buffer + GENERATOR_DATA_BUFFER_SIZE;
1063 this->data_struct = NULL;
1064 this->current_bit = 0;
1065 this->last_payload_length_position_offset = 0;
1066 this->header_length_position_offset = 0;
1067 this->logger = charon->logger_manager->create_logger(charon->logger_manager,GENERATOR,NULL);
1068
1069 return &(this->public);
1070 }