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